Description

Once upon a time, in a faraway land, there lived a king. This king owned a small collection of rare and valuable trees, which had been gathered by his ancestors on their travels. To protect his trees from thieves, the king ordered that a high fence be built around them. His wizard was put in charge of the operation. 
Alas, the wizard quickly noticed that the only suitable material available to build the fence was the wood from the trees themselves. In other words, it was necessary to cut down some trees in order to build a fence around the remaining trees. Of course, to prevent his head from being chopped off, the wizard wanted to minimize the value of the trees that had to be cut. The wizard went to his tower and stayed there until he had found the best possible solution to the problem. The fence was then built and everyone lived happily ever after.

You are to write a program that solves the problem the wizard faced.

Input

The input contains several test cases, each of which describes a hypothetical forest. Each test case begins with a line containing a single integer n, 2 <= n <= 15, the number of trees in the forest. The trees are identified by consecutive integers 1 to n. Each of the subsequent n lines contains 4 integers xi, yi, vi, li that describe a single tree. (xi, yi) is the position of the tree in the plane, vi is its value, and li is the length of fence that can be built using the wood of the tree. vi and li are between 0 and 10,000. 
The input ends with an empty test case (n = 0). 

Output

For each test case, compute a subset of the trees such that, using the wood from that subset, the remaining trees can be enclosed in a single fence. Find the subset with minimum value. If more than one such minimum-value subset exists, choose one with the smallest number of trees. For simplicity, regard the trees as having zero diameter. 
Display, as shown below, the test case numbers (1, 2, ...), the identity of each tree to be cut, and the length of the excess fencing (accurate to two fractional digits).

Display a blank line between test cases.

 

题目大意:有n棵树,每棵树有坐标(x,y),价值v,长度l,问如何砍能砍掉最小价值为的树(价值相同则砍最少的树),能把其他树都围起来
思路:枚举所有砍树的方案(我用的递归,用二进制的方法理论上来说也可以),算一下能不能围起剩下的树(如果价值比当前答案要大就不用算了)。至于怎么围起剩下的树,一个点的明显是需要0长度,两个点就需要这两个点的距离*2,三个点或以上就要用到求凸包的方法(反正我的凸包是不能算三个点以下的)

PS:输出最好复制啊,我好像就是因为forest打错了WA了好几次啊……

  1. #include <cstdio>
  2. #include <cmath>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. const double EPS = 1e-;
  7.  
  8. inline int sgn(const double &x) {
  9. if(fabs(x) < EPS) return ;
  10. return x > ? : -;
  11. }
  12.  
  13. struct Point {
  14. double x, y;
  15. int v, l;
  16. };
  17.  
  18. inline bool Cross(Point &sp, Point &ep, Point &op) {
  19. return (sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y) >= ;
  20. }
  21.  
  22. inline double dist(Point &a, Point &b) {
  23. return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  24. }
  25.  
  26. inline bool cmp(const Point &a, const Point &b) {
  27. if(a.y == b.y) return a.x < b.x;
  28. return a.y < b.y;
  29. }
  30.  
  31. const int MAXN = ;
  32. int stk[MAXN];
  33. bool cut[MAXN], ans[MAXN];
  34. Point p[MAXN], a[MAXN];
  35. int n, top;
  36. double answood;
  37.  
  38. double Graham_scan(int n) {
  39. sort(p, p + n, cmp);
  40. top = ;
  41. stk[] = ; stk[] = ;
  42. for(int i = ; i < n; ++i) {
  43. while(top && Cross(p[i], p[stk[top]], p[stk[top - ]])) --top;
  44. stk[++top] = i;
  45. }
  46. int len = top;
  47. stk[++top] = n - ;
  48. for(int i = n - ; i >= ; --i) {
  49. while(top != len && Cross(p[i], p[stk[top]], p[stk[top - ]])) --top;
  50. stk[++top] = i;
  51. }
  52. double sum = ;
  53. stk[++top] = stk[];
  54. for(int i = ; i < top; ++i)
  55. sum += dist(p[stk[i]], p[stk[i+]]);
  56. return sum;
  57. }
  58.  
  59. int minval, mincut, sumval, sumlen;
  60. double uselen;
  61.  
  62. void setans(int cutcnt) {
  63. for(int i = ; i <= n; ++i) ans[i] = cut[i];
  64. minval = sumval;
  65. mincut = cutcnt;
  66. answood = sumlen - uselen;
  67. }
  68.  
  69. void dfs(int dep, int cutcnt) {
  70. if(dep == n + ) {
  71. if(n == cutcnt) return ;
  72. sumval = sumlen = ;
  73. for(int i = ; i <= n; ++i) {
  74. if(!cut[i]) continue;
  75. sumval += a[i].v;
  76. sumlen += a[i].l;
  77. }
  78. if(sumval > minval) return ;
  79. if(sumval == minval && cutcnt >= mincut) return ;
  80. if(n - cutcnt == ) {
  81. uselen = ;
  82. setans(cutcnt);
  83. }
  84. else if(n - cutcnt == ) {
  85. int i1 = , i2 = ;
  86. for(int i = ; i <= n; ++i) {
  87. if(cut[i]) continue;
  88. if(!i1) i1 = i;
  89. else i2 = i;
  90. }
  91. uselen = * dist(a[i1], a[i2]);
  92. if(uselen <= sumlen) setans(cutcnt);
  93. }
  94. else {
  95. int pcnt = ;
  96. for(int i = ; i <= n; ++i) {
  97. if(cut[i]) continue;
  98. p[pcnt++] = a[i];
  99. }
  100. uselen = Graham_scan(pcnt);
  101. if(sgn(uselen - sumlen) <= ) setans(cutcnt);
  102. }
  103. return ;
  104. }
  105. cut[dep] = false;
  106. dfs(dep + , cutcnt);
  107. cut[dep] = true;
  108. dfs(dep + , cutcnt + );
  109. }
  110.  
  111. int main() {
  112. int ca = ;
  113. while(scanf("%d", &n) != EOF && n) {
  114. for(int i = ; i <= n; ++i) {
  115. scanf("%lf%lf%d%d", &a[i].x, &a[i].y, &a[i].v, &a[i].l);
  116. }
  117. mincut = MAXN;
  118. minval = 0x7fffffff;
  119. dfs(, );
  120. if(ca != ) printf("\n");
  121. printf("Forest %d\n", ca++);
  122. printf("Cut these trees:");
  123. for(int i = ; i <= n; ++i) if(ans[i]) printf(" %d", i);
  124. printf("\nExtra wood: %.2f\n", answood);
  125. }
  126. }

POJ 1873 The Fortified Forest(枚举+凸包)的更多相关文章

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

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

  2. POJ 1873 The Fortified Forest [凸包 枚举]

    The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6400   Accepted: 1 ...

  3. ●POJ 1873 The Fortified Forest

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

  4. POJ 1873 The Fortified Forest

    题意:是有n棵树,每棵的坐标,价值和长度已知,要砍掉若干根,用他们围住其他树,问损失价值最小的情况下又要长度足够围住其他树,砍掉哪些树.. 思路:先求要砍掉的哪些树,在求剩下的树求凸包,在判是否可行. ...

  5. 简单几何(凸包+枚举) POJ 1873 The Fortified Forest

    题目传送门 题意:砍掉一些树,用它们做成篱笆把剩余的树围起来,问最小价值 分析:数据量不大,考虑状态压缩暴力枚举,求凸包以及计算凸包长度.虽说是水题,毕竟是final,自己状压的最大情况写错了,而且忘 ...

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

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

  7. POJ 1873 - The Fortified Forest 凸包 + 搜索 模板

    通过这道题发现了原来写凸包的一些不注意之处和一些错误..有些错误很要命.. 这题 N = 15 1 << 15 = 32768 直接枚举完全可行 卡在异常情况判断上很久,只有 顶点数 &g ...

  8. poj 1873 凸包+枚举

    The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6198   Accepted: 1 ...

  9. poj1873 The Fortified Forest 凸包+枚举 水题

    /* poj1873 The Fortified Forest 凸包+枚举 水题 用小树林的木头给小树林围一个围墙 每棵树都有价值 求消耗价值最低的做法,输出被砍伐的树的编号和剩余的木料 若砍伐价值相 ...

随机推荐

  1. LeetCode 中级 - 优势洗牌(870)

    给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述. 返回 A 的任意排列,使其相对于 B 的优势最大化. 示例 2: 输入: ...

  2. Colored Boots题解

    题目来自Codeforce 1141Dhttp://codeforces.com/problemset/problem/1141/D 因为是全英文题面,就先简单的阐述一下题面. 首先输入一个数n,然后 ...

  3. 【模板】缩点(tarjan,DAG上DP)

    题目背景 缩点+DP 题目描述 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只 ...

  4. Linux磁盘管理和lvm

    磁盘管理 硬盘接口和硬盘种类 从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而SAS ...

  5. MySQL---数据表基本操作(增删改查、排序、分组、连表)

    一.表操作 1.创建表 create table 表名( 列名 类型 是否可以为空, 列名 类型 是否可以为空 )ENGINE=InnoDB DEFAULT CHARSET=utf8 是否可空,nul ...

  6. 用Jquery控制元素的上下移动 实现排序功能

    在页面上,控制元素上下移动,进行排序是我们比较常用的功能,今天我用jQuery 写个 简单方便,功能齐全的实现方式. 话不多说,直接上代码,下面是基础的引入jq和html元素部分: <scrip ...

  7. Spark实际项目中调节并行度

    实际项目中调节并行度 实际项目中调节并行度 并行度概述 spark架构一览 如果不调节并行度,导致并行度过低,会怎么样? 设置spark作业并行度 小结 并行度概述 其实就是指的是,Spark作业中, ...

  8. Vue.js的小例子--随便写的

    1.领导安排明天给同事们科普下vue 2.简单写了两个小例子 3.话不多说直接上代码 <!DOCTYPE html> <html> <head> <meta ...

  9. hdu 2031 进制转换(栈思想的使用)

    进制转换 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  10. 北京Uber优步司机奖励政策(3月19日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...