题目链接:UVA 811

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\le n\le 15\), the number of trees in the forest. The trees are identied by consecutive integers \(1\) to \(n\). Each of the subsequent lines contains \(4\) integers \(x_i,y_i,v_i,l_i\) that describe a single tree. \((x_i,y_i)\) is the position of the tree in the plane, \(v_i\) is its value, and \(l_i\) 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.

Sample Input

  1. 6
  2. 0 0 8 3
  3. 1 4 3 2
  4. 2 1 7 1
  5. 4 1 2 3
  6. 3 5 4 6
  7. 2 3 9 8
  8. 3
  9. 3 0 10 2
  10. 5 5 20 25
  11. 7 -3 30 32
  12. 0

Sample Output

  1. Forest 1
  2. Cut these trees: 2 4 5
  3. Extra wood: 3.16
  4. Forest 2
  5. Cut these trees: 2
  6. Extra wood: 15.00

Solution

题意

有 \(n\) 颗树,每颗树的坐标为 \(x, y\) ,价值为 \(v_i\) 长度为 \(l_i\)。现在要用篱笆将其中一些树围起来,但篱笆制作来源于这些树,即要求砍掉的树能构成篱笆的长度 \(>=\) 剩余树的凸包周长。现在要使得砍掉树的价值之和最小,问需要砍掉哪些树(如果有价值相同的解,就输出砍的树最少的解)。

题解

凸包周长 状态压缩枚举

树的规模比较小,用二进制枚举所有情况即可。

Code

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <vector>
  4. #include <algorithm>
  5. #include <cmath>
  6. using namespace std;
  7. const double eps = 1e-10;
  8. const int inf = 0x3f3f3f3f;
  9. const int maxn = 30;
  10. int n;
  11. struct Point {
  12. double x, y;
  13. int v, l;
  14. int id;
  15. Point() {}
  16. Point(double a, double b) : x(a), y(b) {}
  17. bool operator<(const Point &b) const {
  18. if (x < b.x) return 1;
  19. if (x > b.x) return 0;
  20. return y < b.y;
  21. }
  22. bool operator==(const Point &b) const {
  23. if (x == b.x && y == b.y) return 1;
  24. return 0;
  25. }
  26. Point operator-(const Point &b) {
  27. return Point(x - b.x, y - b.y);
  28. }
  29. } p[maxn], stk[maxn], tmp[maxn];
  30. typedef Point Vec;
  31. int sgn(double x) {
  32. if (fabs(x) <= eps)
  33. return 0;
  34. return x > 0 ? 1 : -1;
  35. }
  36. double dist(Point a, Point b) {
  37. return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
  38. }
  39. double cross(Vec a, Vec b) {
  40. return a.x * b.y - a.y * b.x;
  41. }
  42. int Andrew(int l) {
  43. sort(tmp + 1, tmp + 1 + l);
  44. int len = 0;
  45. for (int i = 1; i <= l; ++i) {
  46. if(i > 1 && tmp[i] == tmp[i - 1]) continue; // 会有重复的点, WA了好几次
  47. while (len > 1 && sgn(cross(stk[len] - stk[len - 1], tmp[i] - stk[len - 1])) == -1) {
  48. len--;
  49. }
  50. stk[++len] = tmp[i];
  51. }
  52. int k = len;
  53. for (int i = l - 1; i >= 1; --i) {
  54. if(i > 1 && tmp[i] == tmp[i - 1]) continue;
  55. while (len > k && sgn(cross(stk[len] - stk[len - 1], tmp[i] - stk[len - 1])) == -1) {
  56. len--;
  57. }
  58. stk[++len] = tmp[i];
  59. }
  60. return len;
  61. }
  62. void solve(int &min_val, int &cur_num, double &re_len, int &ans) {
  63. int size = 1 << n;
  64. for(int bit = 0; bit < size; ++bit) {
  65. int t = 0, cur_val = 0;
  66. double cur_len = 0 ;
  67. for(int i = 0; i < n; ++i) {
  68. if(bit & (1 << i)) {
  69. cur_len += p[i].l;
  70. cur_val += p[i].v;
  71. } else {
  72. tmp[++t] = p[i];
  73. }
  74. }
  75. if(cur_val > min_val) continue;
  76. int cnt = Andrew(t);
  77. double c = 0;
  78. for(int i = 1; i < cnt; ++i) {
  79. c += dist(stk[i], stk[i + 1]);
  80. }
  81. if(cur_len >= c) {
  82. if(cur_val < min_val || (cur_val == min_val && n - t < cur_num)) {
  83. min_val = cur_val;
  84. cur_num = n - t;
  85. re_len = cur_len - c;
  86. ans = bit;
  87. }
  88. }
  89. }
  90. }
  91. int main() {
  92. int kase = 0;
  93. while(scanf("%d",&n) && n) {
  94. if(kase) printf("\n");
  95. for(int i = 0; i < n; ++i) {
  96. scanf("%lf%lf%d%d", &p[i].x, &p[i].y, &p[i].v, &p[i].l);
  97. }
  98. int min_val = inf;
  99. int cur_num = inf;
  100. double re_len = 0;
  101. int ans = 0;
  102. solve(min_val, cur_num, re_len, ans);
  103. printf("Forest %d\n", ++kase);
  104. printf("Cut these trees:");
  105. for(int i = 0 ; i < n; ++i) {
  106. if(ans & (1 << i)) {
  107. printf(" %d", i + 1);
  108. }
  109. }
  110. printf("\nExtra wood: %.2lf\n", re_len);
  111. }
  112. return 0;
  113. }

POJ 1873 UVA 811 The Fortified Forest (凸包 + 状态压缩枚举)的更多相关文章

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

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

  2. UVA 1508 - Equipment 状态压缩 枚举子集 dfs

    UVA 1508 - Equipment 状态压缩 枚举子集 dfs ACM 题目地址:option=com_onlinejudge&Itemid=8&category=457& ...

  3. 状态压缩+枚举 POJ 3279 Fliptile

    题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...

  4. 状态压缩+枚举 UVA 11464 Even Parity

    题目传送门 /* 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 状态压缩+枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 ...

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

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

  6. Uva5211/POJ1873 The Fortified Forest 凸包

    LINK 题意:给出点集,每个点有个价值v和长度l,问把其中几个点取掉,用这几个点的长度能把剩下的点围住,要求剩下的点价值和最大,拿掉的点最少且剩余长度最长. 思路:1999WF中的水题.考虑到其点的 ...

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

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

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

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

  9. POJ 3311 Hie with the Pie(DP状态压缩+最短路径)

    题目链接:http://poj.org/problem?id=3311 题目大意:一个送披萨的,每次送外卖不超过10个地方,给你这些地方之间的时间,求送完外卖回到店里的总时间最小. Sample In ...

随机推荐

  1. jmeter3.0启动时报错误 “unable to access jarfile apachejmeter.jar“

    jdk环境也配置好了.但启动时报错.才发现jmeter3.0的bin目录下没有这个.jar文件.复制了一份放到这个目录下就不报这个错了.

  2. java的继承 和super关键字 构造器

    面向对象的特性二继承: 继承的好处: 1.减少代码的冗余.提高了代码的复用性 2.便于功能的扩展 3.为之后多态的使用,提供了前提 继承的格式: class A extends B{} A:子类.派生 ...

  3. 导数与偏导数 Derivative and Partial Derivative

    之前做了很长时间“罗辑思维”的听众,罗胖子曾经讲起过,我们这一代人该如何学习.其中,就讲到我们这个岁数,已经不可能再去从头到尾的学习一门又一门工具课程了,而是在学习某一领域时,有目的的去翻阅工具课程中 ...

  4. [FW]CLONE_NEWUSER trickery: CVE-2013-1858

    CLONE_NEWUSER trickery: CVE-2013-1858   Recent kernels (3.8+ something) introduced a feature calledu ...

  5. 解决HDFS小文件带来的计算问题

    hive优化 一.小文件简述 1.1. HDFS上什么是小文件? HDFS存储文件时的最小单元叫做Block,Hadoop1.x时期Block大小为64MB,Hadoop2.x时期Block大小为12 ...

  6. SQLServer存储过程学习记录

    简单来说,存储过程就是一条或者多条sql语句的集合,可视为批处理文件,但是其作用不仅限于批处理. 一.存储过程的概述 SQL Server中的存储过程是使用T_SQL编写的代码段.它的目的在于能够方便 ...

  7. java web session共享

    一 搭建环境 操作系统:windows 7 64位 http server:nginx 1.9.7 缓存系统:memcached Servlet容器:apache-tomcat-7.0.65 二 搭建 ...

  8. Fastjson <= 1.2.47 远程命令执行漏洞

    一.漏洞利用过程 查看java版本:java -version jdk版本大1.8 openjdk versin "1.8.0_222" 下载漏洞利用文件:git clone ht ...

  9. ssh-keyscan - 收集 ssh 公钥

    总览 (SYNOPSIS) ssh-keyscan -words [-v46 ] [-p port ] [-T timeout ] [-t type ] [-f file ] [host | addr ...

  10. jieba分词单例模式及linux权限不够情况下tmp_dir自定义

    在linux环境下,没有root权限的情况下,有时会碰到如下问题: Building prefix dict from the default dictionary ... Loading model ...