【poj 1873】 凸包加枚举
题目链接:https://vjudge.net/problem/POJ-1873
题意:给你若干个点(最多15),每个点有两个值 v,l。让你删去某些点,使得总和v最小,且总和l能够包住剩余没选点。直接凸包加枚举OK了。发现G++输出得用%f。。。。。还我1A
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 using namespace std; 7 const int N=20; 8 #define eps 1e-8 9 #define inf 0x3f3f3f3f 10 int sgn(double x){ 11 if(fabs(x)<eps) return 0; 12 if(x<0) return -1; 13 return 1; 14 } 15 struct Point{ 16 double x,y,l; 17 int v; 18 Point operator - (const Point& b)const{ 19 return (Point){x-b.x,y-b.y}; 20 } 21 double operator ^ (const Point& b)const{ 22 return x*b.y-b.x*y; 23 } 24 }p[N],a[N],p0; 25 int sta[N]; 26 int n; 27 bool vis[N]; 28 double dist(Point a,Point b){ 29 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); 30 } 31 bool cmp(Point a,Point b){ 32 if(atan2(a.y-p0.y,a.x-p0.x)!=atan2(b.y-p0.y,b.x-p0.x)){ 33 return (atan2(a.y-p0.y,a.x-p0.x)<atan2(b.y-p0.y,b.x-p0.x)); 34 } 35 return a.x<b.x; 36 } 37 double graham(int cnt){ 38 if(cnt<2) return 0; 39 if(cnt==2) return 2*dist(a[1],a[2]); 40 p0=a[1]; 41 int k=1; 42 for(int i=2;i<=cnt;++i){ 43 if((p0.y > a[i].y) || ((p0.y==a[i].y) && (p0.x>a[i].x))){ 44 p0=a[i]; 45 k=i; 46 } 47 } 48 a[k]=a[1]; 49 a[1]=p0; 50 sort(a+2,a+1+cnt,cmp); 51 sta[0]=1; sta[1]=2; 52 int top=1; 53 for(int i=3;i<=cnt;++i){ 54 while(top>0&&((a[i]-a[sta[top-1]])^(a[sta[top]]-a[sta[top-1]])) >= 0) --top; 55 sta[++top]=i; 56 } 57 double ans=0; 58 for(int i=0;i<top;++i) ans+=dist(a[sta[i]],a[sta[i+1]]); 59 ans+=dist(a[sta[0]],a[sta[top]]); 60 return ans; 61 } 62 int ans[N]; 63 int main(){ 64 int n; 65 int cas=0; 66 while(~scanf("%d",&n) && n){ 67 for(int i=0;i<n;++i) scanf("%lf %lf %d %lf",&p[i].x,&p[i].y,&p[i].v,&p[i].l); 68 int ansv=inf,ansn=inf; 69 double anslef; 70 for(int i=0;i<(1<<n);++i){ 71 memset(vis,0,sizeof(vis)); 72 int temv=0,temn=0; 73 double teml=0; 74 int cnt=0; 75 for(int j=0;j<n;++j){ 76 if((1<<j) & i){ 77 vis[j]=1; 78 ++temn; 79 temv+=p[j].v; 80 teml+=p[j].l; 81 } 82 else a[++cnt]=p[j]; 83 } 84 //cerr<<i<<' '<<temv<<' '<<temn<<' '<<teml<<endl; 85 if(temv > ansv || (temv==ansv && temn > ansn)) continue; 86 double used=graham(cnt); 87 //cerr<<i<<' '<<used<<endl; 88 if(used <= teml){ 89 ansv=temv; 90 anslef=teml-used; 91 ansn=0; 92 for(int u=0;u<n;++u) if(vis[u]) ans[++ansn]=u; 93 } 94 } 95 printf("Forest %d\n",++cas); 96 printf("Cut these trees: "); 97 for(int i=1;i<=ansn;++i) printf("%d ",ans[i]+1); 98 printf("\n"); 99 printf("Extra wood: %.2f\n",anslef); 100 puts(""); 101 } 102 }