【POJ1873】The Fortified Forest-凸包+枚举方案
来源:互联网 发布:删数问题 贪心算法 编辑:程序博客网 时间:2024/06/04 08:50
测试地址:The Fortified Forest
题目大意:有N(2≤N≤15)棵树,每棵树有一个坐标(xi,yi),价值vi,长度li,要砍掉一些树建成围栏防护其他的树,求一个使砍掉的树的价值之和最小的方案,如果有多个方案满足条件,求砍掉的树最少的,输出这种方案中要砍的树的编号,顺便还要输出这种方案下建成围栏之后多余的木材长度。
做法:考虑到N很小,所以我们就枚举方案求最佳方案就可以了。要防护一些树就要把这些树包围起来,而且使得该封闭图形的周长最小,那么显然就是求凸包了,可以用Graham-Scan算法。一个方案合法当且仅当砍掉的树的长度和大于等于围栏的最小长度,在方案合法的基础上求最优方案即可。注意剩下的树为1棵或2棵的情况(只剩1棵树围栏长度为0,剩2棵树围栏长度为两棵树之间距离的两倍),以及C++和G++保留小数的细微不同(C++下用%.2lf,G++下用%.2f),否则会WA到死(像我一样)。
以下是本人代码(话说我的代码风格越来越丑了......):
#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <cmath>#define inf 1000000000#define eps 1e-8using namespace std;int n,tot,anstot=inf,ansval=inf,totval,v[20];double x[20],y[20],l[20],totlen,anslen,dis;bool choice[20]={0},ans[20]={0};struct point {double x,y;} p[20];double multi(point a,point b,point c){ return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);}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 equal(double a,double b){ if (fabs(a-b)<=eps) return 1; else return 0;}bool cmp(point a,point b){ double s=multi(a,b,p[1]); if (!equal(s,0)) return s>0; else return dist(p[1],a)<dist(p[1],b);}double graham_scan(){ for(int i=1;i<=tot;i++) if (p[i].x<p[1].x||(equal(p[i].x,p[1].x)&&p[i].y<p[1].y)){ swap(p[i].x,p[1].x); swap(p[i].y,p[1].y); } sort(p+2,p+tot+1,cmp); int st[20],top=2; st[1]=1,st[2]=2; for(int i=3;i<=tot;i++) { double s=multi(p[st[top]],p[i],p[st[top-1]]); while(s<0&&!equal(s,0)&&top>1){ top--; s=multi(p[st[top]],p[i],p[st[top-1]]);}st[++top]=i; } double len=0; for(int i=2;i<=top;i++) len+=dist(p[st[i]],p[st[i-1]]); len+=dist(p[st[top]],p[st[1]]); return len;}void solve(){ tot=totval=0;totlen=0; for(int i=1;i<=n;i++) { if (choice[i]){ totval+=v[i]; totlen+=l[i];} else{ p[++tot].x=x[i],p[tot].y=y[i];} } if (totval>ansval) return; if (totval==ansval&&n-tot>=anstot) return; if (tot==1) dis=0; else dis=graham_scan(); if (totlen<dis&&!equal(totlen,dis)) return; ansval=totval,anstot=n-tot,anslen=totlen-dis; for(int i=1;i<=n;i++) ans[i]=choice[i];}int main(){ int t=0; while(scanf("%d",&n)&&n) { ++t;if (t>1) printf("\n\n");anstot=inf,ansval=inf;for(int i=1;i<=n;i++) scanf("%lf%lf%d%lf",&x[i],&y[i],&v[i],&l[i]);for(int i=1;i<(1<<n);i++){ int x=i; for(int j=1;j<=n;j++) choice[j]=x&1,x>>=1; solve();}printf("Forest %d\nCut these trees: ",t);for(int i=1;i<=n;i++) if (ans[i]) printf("%d ",i);printf("\nExtra wood: %.2lf",anslen); } return 0;}
0 0
- 【POJ1873】The Fortified Forest-凸包+枚举方案
- poj1873 The Fortified Forest【枚举+凸包】
- poj1873 The Fortified Forest 凸包+枚举 水题
- The Fortified Forest(poj1873位运算枚举+凸包)
- poj1873 The Fortified Forest(位运算枚举+凸包)
- [POJ1873]The Fortified Forest(dfs+凸包)
- POJ 1873 The Fortified Forest 凸包+枚举
- poj 1873 The Fortified Forest(凸包+枚举)
- POJ 1873 The Fortified Forest(凸包+枚举)
- POJ 1873 The Fortified Forest (计算几何,枚举+凸包)
- POJ 1873 The Fortified Forest (枚举+凸包)
- POJ 1873 The Fortified Forest 凸包+枚举组合
- (beginer) 凸包+枚举 UVA 811 - The Fortified Forest
- POJ 1873 The Fortified Forest(凸包+枚举)
- POJ 1873 The Fortified Forest(枚举+凸包+剪枝)
- POJ 1873 The Fortified Forest(凸包+DFS枚举)
- POJ 1873 The Fortified Forest(二进制枚举+凸包)
- poj 1873The Fortified Forest (凸包 二进制枚举)
- Eclipse web项目中Servlet文件无法运行原因
- Python笔记-递归函数、汉诺塔
- 1143: [CTSC2008]祭祀river/2718: [Violet 4]毕业旅行
- IoC控制反转机制
- 解决问题(两步计算)
- 【POJ1873】The Fortified Forest-凸包+枚举方案
- 2. 《活着》
- 方立勋_30天掌握JavaWeb_JSP
- 2016年上半年信息系统项目管理师真题之上午题小虎趣味解答第1-5题
- platform_device与platform_driver
- servlet/filter/listener/interceptor区别与联系
- 解决问题(两步计算)
- mybatis极简教程
- Java之ClassLoader基础知识