题意:有n棵树,每棵树有坐标,价值,和用作篱笆的长度,求选择几棵树做篱笆后,围住剩下的树的总价值最高的方案,如果相同价值,就取用做篱笆的树最少的一种
#include<iostream> #include<stdio.h> #include<string.h> #include<string> #include<stdlib.h> #include<cmath> #include<queue> #include<algorithm> using namespace std; #define rd(x) scanf("%d",&x) #define rdd(x,y) scanf("%d%d",&x,&y) #define rddd(x,y,z) scanf("%d%d%d",&x,&y,&z) #define rdddd(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) #define rds(s) scanf("%s",s) #define rep(i,n) for(int i=0;i<n;i++) #define LL long long const int N = 1e5+10; const int M=2000; const int inf=0x3f3f3f3f; const double eps=1e-9; int MOD=1e9+7; int cas=1; int n,m,k,q,L; int sgn(double x){return x<-eps?-1:x<eps?0:1;} struct Point{ double x,y; double v,l; Point(){} Point(double _x,double _y){ x=_x;y=_y; } }; double cross(Point a,Point b,Point c){ return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x); } bool same(Point a,Point b){ if(sgn(a.x-b.x)==0 && sgn(a.y-b.y)==0) return true; return false; } double dist(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } bool cmp(const Point &a,const Point &b){ if(sgn(a.y-b.y)==0) return a.x<b.x; return a.y<b.y; } Point tmp; bool cmp2(const Point &a,const Point &b){ int d=sgn(cross(tmp,a,b)); if(!d) return dist(tmp,a)<dist(tmp,b); else{ return d>0; } } Point p[20],convex[20]; double solve(Point p[],int n){ if(n==1) return 0; if(n==2) return dist(p[0],p[1])*2; int mi=0; for(int i=1;i<n;i++) if(cmp(p[i],p[mi])) mi=i; swap(p[mi],p[0]); tmp=p[0]; sort(p+1,p+n,cmp2); int top=0; convex[top++]=p[0]; convex[top++]=p[1]; int k=2; while(k<=n){ while(top>=2 && sgn(cross(convex[top-2],convex[top-1],p[k%n]))<=0 ) top--; convex[top++]=p[k%n]; k++; } double ans=0; if(top<=1) return 0; else if(top==2) return dist(convex[0],convex[1]); else{ for(int i=0;i<top;i++) ans+=dist(convex[i],convex[(i+1)%top]); } return ans; } Point tp[20]; int id[20]; int tid[20]; int main() { #ifndef ONLINE_JUDGE freopen("aaa","r",stdin); #endif int T; while(1){ rd(n); if(!n) break; for(int i=0;i<n;i++){ scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].v,&p[i].l); } int use_num=100; double left_v=-1; double extra; int N=1<<n; for(int i=1;i<N-1;i++){ int cnt=0; double use_len=0; double v=0; int sz=0; for(int j=0;j<n;j++){ if((i>>j)&1){ use_len+=p[j].l; id[cnt++]=j; }else { tp[sz++]=p[j]; v+=p[j].v; } } double len=solve(tp,sz); int ret=sgn(use_len-len); if(ret>=0){ int t=sgn(v-left_v); if(t>0){ left_v=v; use_num=cnt; extra=use_len-len; for(int j=0;j<use_num;j++) tid[j]=id[j]; }else if(!t && use_num>cnt){ use_num=cnt; extra=use_len-len; for(int j=0;j<use_num;j++) tid[j]=id[j]; } } } printf("Forest %d\n",cas++); printf("Cut these trees:"); for(int i=0;i<use_num;i++) printf(" %d",tid[i]+1); puts(""); printf("Extra wood: %.2f\n\n",extra); } return 0; }