按位枚举,按最小价值,最小砍掉树剪枝就好了。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int MAXN=20; const int inf=190000000; int n,l; int st[MAXN],stop,cnt; int ans[MAXN]; bool cut[MAXN]; struct point{ int x,y; int len,val; int num; }p[MAXN]; int ansV,ansC; double anslen; bool cmp(point A,point B){ if(A.y<B.y) return true; else if(A.y==B.y){ if(A.x<B.x) return true; } return false; } bool cmp1(int a,int b){ if(a<b) return true; return false; } bool multi(point a,point b,point c){ return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x)<=0; } double dist(point a, point b){ return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)*1.0); } double for_len(){ if(cnt==1) return 0; double res=0; for(int i=1;i<cnt;i++) res+=dist(p[ans[i]],p[ans[i-1]]); return (res); } void slove(){ stop=0; cnt=0; int choice=0; int be; for(int i=0;i<n;i++){ if(!cut[i]){ st[stop++]=i; choice++; } if(choice==2){ be=i; break; } } if(choice<2){ cnt=1; return ; } for(int i=be+1;i<n;i++){ if(cut[i]) continue; while(stop>1&&multi(p[st[stop-1]],p[i],p[st[stop-2]])) stop--; st[stop++]=i; } for(int i=0;i<stop;i++){ ans[cnt++]=st[i]; } stop=0; choice=0; for(int i=n-1;i>=0;i--){ if(!cut[i]){ st[stop++]=i; choice++; } if(choice==2){ be=i; break; } } for(int i=be-1;i>=0;i--){ if(cut[i]) continue; while(stop>1&&multi(p[st[stop-1]],p[i],p[st[stop-2]])) stop--; st[stop++]=i; } for(int i=0;i<stop;i++) ans[cnt++]=st[i]; } int main(){ int cas=0; while(scanf("%d",&n)!=EOF){ if(n==0) break; cas++; for(int i=0;i<n;i++){ scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].val,&p[i].len); p[i].num=i+1; } sort(p,p+n,cmp); ansV=inf; int tmpV; int tmpC; double len; int CUT=inf; for(int i=1;i<(1<<n);i++){ tmpV=0; tmpC=0; len=0; memset(cut,false,sizeof(cut)); for(int k=0;k<n;k++){ if((1<<k)&i){ cut[k]=true; tmpV+=p[k].val; tmpC++; len+=p[k].len; } } if(tmpV<ansV){ slove(); double res=for_len(); if(res<=len){ CUT=tmpC; ansV=tmpV; ansC=i; anslen=len*1.0-res; } } else if(tmpV==ansV){ if(CUT>tmpC){ slove(); double res=for_len(); if(res<=len){ CUT=tmpC; ansV=tmpV; ansC=i; anslen=len*1.0-res; } } } } printf("Forest %d\n",cas); printf("Cut these trees:"); cnt=0; for(int k=0;k<n;k++) if((1<<k)&ansC){ st[cnt++]=p[k].num; } sort(st,st+cnt,cmp1); for(int i=0;i<cnt;i++) printf(" %d",st[i]); printf("\n"); printf("Extra wood: %0.2lf\n",anslen); printf("\n"); } return 0; }
时间: 2024-10-12 23:52:06