版权声明:欢迎复制!!! https://blog.csdn.net/qq_37493070/article/details/81782953
地址: 传送门在此
题意
给你n个树,给你每个树的坐标 x,y 还有 价值v 每个点有一个长度l ,你需要选几颗树砍了做围栏把剩下的树围起来,输出价值最小的方案,和剩下的木板,如果存在多个相同的价值,取数量最小的
做法
n<15 ,可以直接暴力枚举,用二进制表示每一种状态 , vector 会超时
代码
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define ll long long
#define rd(a) scanf("%d",&a)
#define rld(a) scanf("%lld",&a)
#define rs(a) scanf("%s",a)
#define me(a,b) memset(a,b,sizeof(a))
#define pb(a) push_back(a)
const ll maxn=3e5+10;
const ll mod =1e9+7;
const ll inf =0x3f3f3f3f;
const double PI=acos(-1);
struct paint{
int x;
int y;
paint(){}
paint(int xx,int yy):x(xx),y(yy){}
bool friend operator <(const paint &a,const paint &b){
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
bool friend operator ==(const paint &a,const paint &b){
return a.x==b.x&&a.y==b.y;
}
paint friend operator -(const paint &a,const paint &b){
return paint(a.x-b.x,a.y-b.y);
}
};
int cross(paint a,paint b){
return a.x*b.y-b.x*a.y;
}
double dis(paint a,paint b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
paint w[30];
int Andrew(vector<paint>p){
int n=p.size();
sort(p.begin(),p.end());
int m=0;
for(int i=0;i<n;i++)
{
while(m>1&&cross(w[m-1]-w[m-2],p[i]-w[m-2])<=0) m--;
w[m++]=p[i];
}
int o=m;
for(int i=n-2;i>=0;i--){
while(m>o&&cross(w[m-1]-w[m-2],p[i]-w[m-2])<=0) m--;
w[m++]=p[i];
}
if(n>1) m--;
return m;
}
paint p[30];
int v[30];
int len[30];
int main(){
int n;
int tt=1;
while(~rd(n)&&n){
for(int i=0;i<n;i++)
{
rd(p[i].x),rd(p[i].y),rd(v[i]),rd(len[i]);
}
double minn=inf;
double minn_s=inf;
int minn_size=n;
int jl=-1;
vector<paint>q;
for(int i=1;i<(1<<n);i++){
double ans_len=0;
double ans_v=0;
q.clear();
for(int j=0;j<n;j++){
if(i&(1<<j)) q.pb(p[j]);
else ans_len+=len[j],ans_v+=v[j];
}
int siz=n-q.size();
int m=Andrew(q);
double ans_lg=dis(w[0],w[m-1]);;
for(int j=1;j<m;j++){
ans_lg+=dis(w[j],w[j-1]);
}
if(ans_lg<=ans_len&&ans_v<minn){
minn=ans_v;
minn_s= ans_len-ans_lg;
jl=i;
minn_size=siz;
}
else if(ans_lg<=ans_len&&ans_v==minn&&siz<minn_size){
minn=ans_v;
minn_s= ans_len-ans_lg;
jl=i;
minn_size=siz;
}
}
printf("Forest %d\nCut these trees:",tt++);
int i=1;
for(int j=0;j<n;j++){
if(!(jl&(1<<j))) printf(" %d",j+1);
}
printf("\nExtra wood: %.2f\n\n",minn_s);
}
return 0;
}