标签:
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 6115 | Accepted: 1720 |
Description
Input
Output
Sample Input
6 0 0 8 3 1 4 3 2 2 1 7 1 4 1 2 3 3 5 4 6 2 3 9 8 3 3 0 10 2 5 5 20 25 7 -3 30 32 0
Sample Output
Forest 1 Cut these trees: 2 4 5 Extra wood: 3.16 Forest 2 Cut these trees: 2 Extra wood: 15.00
题意:国王有一些树,他想砍掉一些树做篱笆围住剩下的树,每棵树都有坐标,价值和做成篱笆长度,我们应该使砍掉的树的价值尽可能的小并且做成的篱笆能够围住剩下的树,如果方案的价值相同选择砍掉数量
少的,最后输出砍掉的树的编号和篱笆围了之后还能剩下多少。
题解:深坑啊。。。WA了好多次,竟然是cmp函数里面的变量p[0]的函数名冲突了...world final的水题都好难。。过,但是想法不难。。就是每次枚举那些树不取和取,不超过2^15次方,用二进制表示..然后再进行凸包。。比较。。
#include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <algorithm> #include <stdlib.h> using namespace std; const double eps = 1e-8; const int N = 20; struct Point { double x,y,value,len; } p[N],q[N]; Point Stack[N]; int n; double cross(Point a,Point b,Point c) { return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x); } double dis(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Point po; //大坑 int cmp(Point a,Point b) { if(cross(a,b,po)>0) return 1; if(cross(a,b,po)==0&&dis(b,po)-dis(a,po)>eps) return 1; return 0; } double Graham(Point p[],int n) { if(n==0||n==1) return 0; if(n==2) return 2*dis(p[0],p[1]); int k =0; for(int i=0; i<n; i++) { if(p[k].y>p[i].y||((p[k].y==p[i].y)&&(p[k].x>p[i].x))) k=i; } swap(p[0],p[k]); po = p[0]; ///嗯,这里 int top=2; sort(p+1,p+n,cmp); Stack[0]=p[0]; Stack[1]=p[1]; Stack[2]=p[2]; for(int i=3; i<n; i++) { while(top>=1&&cross(p[i],Stack[top],Stack[top-1])>=0) { top--; } Stack[++top]=p[i]; } double ans = 0; for(int i=1; i<=top; i++) { ans+=dis(Stack[i],Stack[i-1]); } ans+=dis(Stack[top],Stack[0]); return ans; } int main() { int _count = 1; while(scanf("%d",&n)!=EOF&&n) { for(int i=0; i<n; i++) { scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].value,&p[i].len); } int t = (1<<n)-1; int cnt[N],id[N];///保存要砍掉的树的编号 double save=0; int num=999999999; ///要砍掉的数的数目 double mi=999999999; ///保存要砍掉的树的最小价值 for(int i=1; i<t; i++) ///1代表砍掉这棵树,0代表不砍,至少要砍一棵树 { double value=0,len=0; int k=0,k1=0; for(int j=0; j<n; j++) { if((i>>j)&1) ///移位操作,表示当前第j+1棵树要砍掉 { cnt[k++] = j; value+=p[j].value; len+=p[j].len; } else q[k1++] = p[j]; } double L = Graham(q,k1); if(len-L>eps) ///如果能够组成的篱笆长度大于凸包周长 { if(mi-value>eps||(fabs(value-mi)<eps&&k<num)) { mi = value; for(int j=0; j<k; j++) id[j]=cnt[j]; num = k; save = len - L; } } } printf("Forest %d\nCut these trees: ",_count++); for(int i=0; i<num; i++) { printf("%d ",id[i]+1); } printf("\nExtra wood: %.2lf\n\n",save); } return 0; }
标签:
原文地址:http://www.cnblogs.com/liyinggang/p/5449635.html