LINK

题意:给出点集,每个点有个价值v和长度l,问把其中几个点取掉,用这几个点的长度能把剩下的点围住,要求剩下的点价值和最大,拿掉的点最少且剩余长度最长。

思路:1999WF中的水题。考虑到其点的数量最多只有15个,那么可以使用暴力枚举所有取点情况,二进制压缩状态,预处理出该状态下的价值,同时记录该状态拥有的点,并按价值排序。按价值枚举状态,并对拥有的这些点求凸包,check是否合法,找到一组跳出即可。然而POJ似乎没有SPJ,同样的代码POJ会超时,UVA60ms,可以在常数上优化,不预处理,实时判价值最大值,不使用结构体等

  1. /** @Date : 2017-07-16 14:48:08
  2. * @FileName: POJ 1873 凸包.cpp
  3. * @Platform: Windows
  4. * @Author : Lweleth (SoungEarlf@gmail.com)
  5. * @Link : https://github.com/
  6. * @Version : $Id$
  7. */
  8. #include <stdio.h>
  9. #include <iostream>
  10. #include <string.h>
  11. #include <algorithm>
  12. #include <utility>
  13. #include <vector>
  14. #include <map>
  15. #include <set>
  16. #include <string>
  17. #include <stack>
  18. #include <queue>
  19. #include <math.h>
  20. //#include <bits/stdc++.h>
  21. #define LL long long
  22. #define PII pair<int ,int>
  23. #define MP(x, y) make_pair((x),(y))
  24. #define fi first
  25. #define se second
  26. #define PB(x) push_back((x))
  27. #define MMG(x) memset((x), -1,sizeof(x))
  28. #define MMF(x) memset((x),0,sizeof(x))
  29. #define MMI(x) memset((x), INF, sizeof(x))
  30. using namespace std;
  31.  
  32. const int INF = 0x3f3f3f3f;
  33. const int N = 1e5+20;
  34. const double eps = 1e-8;
  35.  
  36. struct point
  37. {
  38. double x, y;
  39. point(){}
  40. point(double _x, double _y){x = _x, y = _y;}
  41. point operator -(const point &b) const
  42. {
  43. return point(x - b.x, y - b.y);
  44. }
  45. double operator *(const point &b) const
  46. {
  47. return x * b.x + y * b.y;
  48. }
  49. double operator ^(const point &b) const
  50. {
  51. return x * b.y - y * b.x;
  52. }
  53. };
  54.  
  55. double xmult(point p1, point p2, point p0)
  56. {
  57. return (p1 - p0) ^ (p2 - p0);
  58. }
  59.  
  60. double distc(point a, point b)
  61. {
  62. return sqrt((double)((b - a) * (b - a)));
  63. }
  64.  
  65. int sign(double x)
  66. {
  67. if(fabs(x) < eps)
  68. return 0;
  69. if(x < 0)
  70. return -1;
  71. else
  72. return 1;
  73. }
  74. ////////////
  75.  
  76. point pt[50];
  77. int v[50], l[50];
  78. struct yuu
  79. {
  80. point p[50];
  81. int val;
  82. int cnt;
  83. int len;
  84. int sta;
  85. double cst;
  86. void init(){cnt = len = val = cst = 0;}
  87. }tt[1 << 16];
  88.  
  89. point stk[50];
  90.  
  91. /*int cmpA(point a, point b)//以p[0]基准 极角序排序
  92. {
  93. int t = xmult(a, b, p[0]);
  94. if(t > 0)
  95. return 1;
  96. if(t == 0)
  97. return distc(a, p[0]) < distc(b, p[0]);
  98. if(t < 0)
  99. return 0;
  100. }*/
  101.  
  102. int cmpB(yuu a, yuu b)//预处理用
  103. {
  104. if(a.val == b.val)
  105. return a.cnt < b.cnt;
  106. return a.val < b.val;
  107. }
  108.  
  109. int cmpC(point a, point b)//水平序排序
  110. {
  111. return sign(a.x - b.x) < 0 || (sign(a.x - b.x) == 0 && sign(a.y - b.y) < 0);
  112. }
  113.  
  114. /*void grahamS()
  115. {
  116. while(!s.empty())
  117. s.pop();
  118. for(int i = 0; i < min(n, 2); i++)
  119. s.push(i);
  120. int t = 1;
  121. for(int i = 2; i < n; i++)
  122. {
  123. while(s.size() > 1)
  124. {
  125. int p2 = s.top();
  126. s.pop();
  127. int p1 = s.top();
  128. if(xmult(p[p1], p[p2], p[i]) > 0)
  129. {
  130. s.push(p2);
  131. break;
  132. }
  133. }
  134. s.push(i);
  135. }
  136. }*/
  137.  
  138. int graham(int st)//水平序
  139. {
  140. sort(tt[st].p, tt[st].p + tt[st].cnt, cmpC);
  141. int top = 0;
  142. for(int i = 0; i < tt[st].cnt; i++)
  143. {
  144. while(top >= 2 && sign(xmult(stk[top - 2], stk[top - 1], tt[st].p[i])) <= 0)
  145. top--;
  146. stk[top++] = tt[st].p[i];
  147. }
  148. int tmp = top;
  149. for(int i = tt[st].cnt - 2; i >= 0; i--)
  150. {
  151. while(top > tmp && sign(xmult(stk[top - 2],stk[top - 1] ,tt[st].p[i] )) <= 0)
  152. top--;
  153. stk[top++] = tt[st].p[i];
  154. }
  155. if(tt[st].cnt > 1)
  156. top--;
  157. return top;
  158. }
  159.  
  160. int check(int st)
  161. {
  162. int ma = graham(st);
  163. double ans = 0;
  164. stk[ma] = stk[0];
  165. for(int i = 0; i < ma; i++)
  166. ans += distc(stk[i + 1], stk[i]);
  167. tt[st].cst = ans;
  168. if(sign(tt[st].len - ans) < 0)
  169. return 0;
  170. return 1;
  171. }
  172.  
  173. int main()
  174. {
  175. int n;
  176. int cc = 0;
  177. while(~scanf("%d", &n) && n)
  178. {
  179. if(cc)
  180. printf("\n");
  181. cc++;
  182. double x, y;
  183. for(int i = 0; i < n; i++)
  184. {
  185. scanf("%lf%lf%d%d", &x, &y, v + i, l + i);
  186. pt[i] = point(x, y);
  187. }
  188. int c = 0;
  189. for(int st = 0; st < (1 << n); st++)//预处理
  190. {
  191. tt[st].sta = st;
  192. tt[st].init();
  193. c = 0;
  194. for(int i = 0; i < n; i++)
  195. {
  196. if(st & (1 << i))
  197. tt[st].len += l[i], tt[st].val += v[i];
  198. else
  199. tt[st].p[c++] = pt[i];
  200.  
  201. }
  202. tt[st].cnt = c;
  203. }
  204. sort(tt, tt + (1 << n), cmpB);
  205.  
  206. //////
  207. for(int st = 0; st < (1 << n); st++)//遍历
  208. {
  209. if(check(st))
  210. {
  211. printf("Forest %d\n", cc);
  212. printf("Cut these trees:");
  213. for(int i = 0; i < n; i++)
  214. {
  215. if(tt[st].sta & (1 << i))
  216. printf(" %d", i + 1);
  217. }
  218. printf("\nExtra wood: %.2lf\n", ((double)tt[st].len - tt[st].cst + eps));
  219. break;
  220. }
  221. }
  222. }
  223. return 0;
  224. }

Uva5211/POJ1873 The Fortified Forest 凸包的更多相关文章

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

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

  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 凸包 + 搜索 模板

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

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

    题目链接:UVA 811 Description Once upon a time, in a faraway land, there lived a king. This king owned a ...

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

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

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

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

  7. POJ 1873 The Fortified Forest(枚举+凸包)

    Description Once upon a time, in a faraway land, there lived a king. This king owned a small collect ...

  8. The Fortified Forest - POJ 1873(状态枚举+求凸包周长)

    题目大意:有个国王他有一片森林,现在他想从这个森林里面砍伐一些树木做成篱笆把剩下的树木围起来,已知每个树都有不同的价值还有高度,求出来砍掉那些树可以做成篱笆把剩余的树都围起来,要使砍伐的树木的价值最小 ...

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

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

随机推荐

  1. 互评Alpha版本 - Hello World团队项目空天猎

    在测评该项目时,我找到了Hello World!团队的git,并下载了相关文件以及阅读了程序运行说明. 如图所示,我下载了一个名为 SkyHunter1.0.rar 的压缩文件包,文件包内容如下: 根 ...

  2. 软工1816 · 第八次作业(课堂实战)- 项目UML设计(团队)

    本次作业博客 团队信息 队名:起床一起肝活队 原组长: 白晨曦(101) 原组员: 李麒 (123) 陈德斌(104) 何裕捷(214) 黄培鑫(217) 王焕仁(233) 林志华(128) 乐忠豪( ...

  3. [二叉查找树] 1115. Counting Nodes in a BST (30)

    1115. Counting Nodes in a BST (30) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Y ...

  4. 自定义ClassLoader,用于加载用户JAR包

    最近在考虑C/S结构程序的软件自动升级的实现方式,比如QQ.飞信等都自动升级的功能. 自动升级模块虽然还没有编码完成,但是思路还是比较清晰的. 自动升级过程中,升级文件的JAR包是专门加载到程序中去的 ...

  5. Microsoft Orleans 之 开发人员指南

    开发一个Grain 在开发Grain之前请先阅读Grains 这篇文章 Grain 接口 Grains通过调用各自定义在接口中的方法相互作用,一个grain实现了事先定义好的一个或多个接口,grain ...

  6. 【acm】杀人游戏(hdu2211)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2211 杀人游戏 Time Limit: 3000/1000 MS (Java/Others)    M ...

  7. 【beta】Scrum站立会议第4次....11.6

    小组名称:nice! 组长:李权 成员:于淼  刘芳芳韩媛媛 宫丽君 项目内容:约跑app(约吧) 时间:  12:00——12:30 地点:传媒西楼220室 本次对beta阶段的需求进行更新如下: ...

  8. Java Map 在put值时value值不被覆盖

    一.问题描述 最近在代码开发中遇到一个问题,在往Map中put文件路径值然后把Map放到List中去时,遇到问题是Map的后一个值总是把前一个值覆盖,导致最后Map中只有一个值. 二.解决办法(有如下 ...

  9. 第189天:BOM属性方法

    一.BOM---location 1.访问页面 location.href = "http://www.baidu.com"; location.assign("http ...

  10. hadoop跑第一个实例过程

    第一次跑hadoop实例,中间经过了不少弯路,特此记录下来: 第一步:建立一个maven过程,pom.xml文件:(打包为jar包) <dependency> <groupId> ...