题目链接:http://poj.org/problem?id=1873

题目大意:给出n棵树的位置(x,y)坐标,价值v和长度l。让你从中选择一些树,砍掉他们将其他的树围起来。

要求砍的这些树的价值之和最小。按顺序输出砍的树。如果价值相同,输出砍的树最少的的方案。最后在输出一个:砍掉的这些树,围城围栏之后,还剩下多少长度的木头。

思路:一开始很懵逼的。。但是看数据范围这么小,还以为是状压DP,但是出在了凸包专题中,就想怎么用凸包解决(最后证明就是凸包,什么状压DP都是假的)。但毕竟还是WF的题。需要考虑的东西有点多,DFS搜索所有砍树的情况,对于每种情况,都计算一遍所需要的凸包(即求所谓长度),然后从中选择所需要val最少的那个情况。从砍1棵树开始枚举的话,可以直接得出最少的砍树情况。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>
#include<string.h>
#include<math.h> #include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std; #define ll long long
#define Pair pair<int,int>//,pair<int,int> >
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=3e2+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;
const double EPS=1.0e-8;
const double PI=acos(-1.0);//需要自己写文件读入scanf和getchar()都不能用。
//freopen("1.txt","r",stdin);
namespace fastIO {#define BUF_SIZE 100000//fread -> readbool IOerror = 0;inline char nc() {static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;if(p1 == pend) {p1 = buf;pend = buf + fread(buf, 1, BUF_SIZE, stdin);if(pend == p1) {IOerror = 1;return -1;}}return *p1++;}inline bool blank(char ch) {return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';}inline void read(int &x) {char ch;while(blank(ch = nc()));if(IOerror) return;for(x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');}#undef BUF_SIZE
};
using namespace fastIO;struct Point{double x,y,v,l;Point(double _x=0,double _y=0,double _v=0,double _l=0){x=_x;y=_y;v=_v;l=_l;}friend Point operator + (const Point &a,const Point &b){return Point(a.x+b.x,a.y+b.y);}friend Point operator - (const Point &a,const Point &b){return Point(a.x-b.x,a.y-b.y);}friend double operator ^ (Point a,Point b){//向量叉乘 return a.x*b.y-a.y*b.x;}
};
struct V{Point start,end;double ang;V(Point _start=Point(0,0),Point _end=Point(0,0),double _ang=0.0){start=_start;end=_end;ang=_ang;}friend V operator + (const V &a,const V &b){return V(a.start+b.start,a.end+b.end);}friend V operator - (const V &a,const V &b){return V(a.start-b.start,a.end-b.end);}
};
Point v[MAXN],p[MAXN];
int ans[MAXN],stk[MAXN];
int vst[MAXN];//标记是否被砍掉 1砍掉,0不砍
double extra,minv;
int n,nown,ansn;int Cmp(Point a,Point b){if(a.y==b.y)return a.x<b.x;return a.y<b.y;
}
double Multi(Point a,Point b,Point c,Point d){b=b-a;d=d-c;return b^d;
}
int turn_left(Point a,Point b,Point c){return Multi(a,b,b,c)>0;
}
double Dist(Point a,Point b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double Judge(){//求取凸包 int top=1;stk[0]=0;sort(p,p+nown,Cmp);//对加入点集p的点进行排列。 for(int i=1;i<nown;){if(top==1||turn_left(p[stk[top-2]],p[stk[top-1]],p[i])) stk[top++]=i++;else --top;}int t_top=top;for(int i=nown-2;i>=0;){if(top==t_top||turn_left(p[stk[top-2]],p[stk[top-1]],p[i])) stk[top++]=i--;else --top;}double ret=0.0;//获得凸包的围墙长度。 for(int i=0;i<top-1;++i){ret+=Dist(p[stk[i]],p[stk[i+1]]); }return ret;
}
void dg(int deep,int num,double val,double len,int from){//DFS,枚举所有的方法. //       0       i           0           0       0if(deep==num){if(val>minv) return ;//所需要的价值更大 舍去 int temp=0;for(int k=0;k<n;++k){if(!vst[k]){p[temp++]=v[k];//向点集p中添加没有被砍掉的点。 }}double dis=Judge();//需要的围墙长度 if(len>=dis){//长度符合要求 if(val<minv){//所需要的价值更小 minv=val;//刷新价值 extra=len-dis;//损失的长度 ansn=0; for(int k=0;k<n;++k){//ans数组刷新 if(vst[k]){ans[ansn++]=k+1;}}}}return ;}for(int i=from;i<(n-(num-deep-1));++i){//搜索 vst[i]=1;dg(deep+1,num,val+v[i].v,len+v[i].l,i+1);vst[i]=0;}
}
int main(){int cnt=1;while(~scanf("%d",&n)){if(n==0) break;for(int i=0;i<n;++i){scanf("%lf%lf%lf%lf",&v[i].x,&v[i].y,&v[i].v,&v[i].l);}minv=2e9;for(int i=1;i<=n-1;++i){nown=n-i;memset(vst,0,sizeof(vst));dg(0,i,0,0,0);}printf("Forest %d\n",cnt++);printf("Cut these trees:");for(int i=0;i<ansn;++i){printf(" %d",ans[i]);}putchar('\n');printf("Extra wood: %.2f\n\n",extra);}
}
/*
60  0  8  31  4  3  22  1  7  14  1  2  33  5  4  62  3  9  8
33  0 10  25  5 20 257 -3 30 32
0*/

POJ-1873-The Fortified Forest(二进制枚举+凸包)相关推荐

  1. POJ 1873 The Fortified Forest(枚举+凸包+剪枝)

    POJ 1873 The Fortified Forest 题意: 某王有一些树,要制作一个栅栏将所有树围起来,栅栏制作木材来源就是砍去其中一些树. 现在输入每棵树的坐标,价值,高度,求出所围价值最大 ...

  2. POJ 1873 The Fortified Forest 凸包 二进制枚举

    n最大15,二进制枚举不会超时.枚举不被砍掉的树,然后求凸包 #include<stdio.h> #include<math.h> #include<algorithm& ...

  3. poj 1873 The Fortified Forest (位运算枚举 + 凸包周长)

    题目链接:http://poj.org/problem?id=1873 大意:有一片N棵树的森林,要从中砍掉几棵树做成篱笆,把剩下的树围起来 输入:给N课树,每棵树的坐标是x,y,每棵树有一个vi和l ...

  4. POJ 1873 The Fortified Forest (凸包,状态压缩枚举)

    题目链接:http://poj.org/problem?id=1873 题意:给出一些树,每棵树有坐标,高度,以及价值,要求砍掉一些树,用那些木材,将其它树围起来,要求花最小的代价,代价相同,要求砍掉 ...

  5. POJ 1873 The Fortified Forest(凸包)

    http://poj.org/problem?id=1873 题目大意: 给你n棵树每棵树的坐标,高度,价值,要求砍掉一些树,用那些木材,将其它树围起来,要求花最小的代价,代价相同,要求砍掉最少的树. ...

  6. POJ 1873 The Fortified Forest(凸包)题解

    题意:二维平面有一堆点,每个点有价值v和删掉这个点能得到的长度l,问你删掉最少的价值能把剩余点围起来,价值一样求删掉的点最少 思路:n<=15,那么直接遍历2^15,判断每种情况.这里要优化一下 ...

  7. ●POJ 1873 The Fortified Forest

    题链: http://poj.org/problem?id=1873 题解: 计算几何,凸包 枚举被砍的树的集合.求出剩下点的凸包.然后判断即可. 代码: #include<cmath> ...

  8. The Fortified Forest UVALive - 5211 [二进制枚举+凸包周长]

    The Fortified Forest UVALive - 5211 题意:n棵树,每棵树对应有x,y,v,l分别代表横坐标,纵坐标,价值,砍这棵树能构成的篱笆长度.现在要求输出,在最小被砍价值的情 ...

  9. uva 811 - The Fortified Forest(暴力+凸包)

    题目链接:uva 811 - The Fortified Forest 最多就15棵树,枚举哪些树要砍,剩下的做凸包. #include <cstdio> #include <cst ...

最新文章

  1. Python远程部署利器Fabric详解
  2. 牛客小白月赛12:月月给华华出题(欧拉函数)
  3. Spring框架 DI
  4. Linux环境变量PS1配置
  5. vim python补全_转:VIM python 自动补全插件:pydiction
  6. C/C++_宏定义神仙级用法 实现枚举字符串互转
  7. MySql表空间的概念
  8. 淘宝/天猫收货地址列表 API和快递费用的 API解析
  9. pc恶意程序木马分析 启动流程 逆向分析 数据解密
  10. ajax removeclass,Ajax成功后的jQuery addClass/removeClass
  11. poj1606 Jugs(BFS)
  12. 100层楼2个鸡蛋,测试其最低破碎楼层问题
  13. SLAM在机器人中的应用尽如此之广
  14. vue公共组件封装及传值
  15. uniapp微信头像
  16. hdu 1686 Oulipo(kmp)
  17. DICOM笔记-解析JPEG压缩格式DCM文件
  18. 【网络工程零基础】小白零基础,详细教程一看就能学会
  19. 判断推理——类比推理
  20. 灰度共生矩阵(超简单理解)

热门文章

  1. 中国数字人民币官方宣传片来袭!DCEP:开启“无现金新时代”!
  2. Keycloak的搭建
  3. 新手运营APP总结:把握住APP核心价值!
  4. 对云计算的定义,分别从横向和纵向进行分析和归纳
  5. C# 数据库通用类
  6. ChatGPT | 分享论文 Rebuttal、Review 时可能会用到的 Prompt
  7. 安卓游戏常见问题nbsp;黑屏/闪退/…
  8. 手把手教你如何用飞桨自动生成二次元人物头像
  9. 局域网Ping不通防火墙设置
  10. 【互联网企业名称由来系列】四:网易