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

题意:给出一些树,每棵树有坐标,高度,以及价值,要求砍掉一些树,用那些木材,将其它树围起来,要求花最小的代价,代价相同,要求砍掉最少的树。

最后输出要砍掉哪几棵树和最后剩下多少长度的木材。

输入:

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

n棵树,每行一棵,坐标,价值,高度。

因为树的棵数不多,所以可以直接状态压缩枚举来做,枚举时要注意判断砍0棵树的情况。

2^15次方,然后对剩下的树求一次凸包,求出凸包周长,判断木材是否够用,记录最优解。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x) {if(fabs(x) < eps)return 0;if(x < 0)return -1;  else return 1;
}
struct Point {  double x,y, v, l;Point(){}  Point(double _x,double _y) {   x = _x;y = _y;  }  Point operator -(const Point &b)const {return Point(x - b.x,y - b.y);  }  double operator ^(const Point &b)const {return x*b.y - y*b.x;  }    double operator *(const Point &b)const {   return x*b.x + y*b.y;  }  void transXY(double B) {   double tx = x,ty = y;   x = tx*cos(B) - ty*sin(B);   y = tx*sin(B) + ty*cos(B);  }
};struct Line {  Point s,e; Line(){}  Line(Point _s,Point _e)  {s = _s;e = _e;  } pair<int,Point> operator &(const Line &b)const {Point res = s;if(sgn((s-e)^(b.s-b.e)) == 0) {if(sgn((s-b.e)^(b.s-b.e)) == 0) return make_pair(0,res);             else return make_pair(1,res);         } double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));res.x += (e.x-s.x)*t;         res.y += (e.y-s.y)*t;         return make_pair(2,res);     }
};double dist(Point a,Point b) {     return sqrt((a-b)*(a-b));
}const int MAXN = 1010;
Point list[MAXN];
int Stack[MAXN], top;
bool _cmp(Point p1,Point p2) {  double tmp = (p1-list[0])^(p2-list[0]);  if(sgn(tmp) > 0)return true;  else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0)   return true;  else return false;
}
void Graham(int n) {Point p0;int k = 0;p0 = list[0];  for(int i = 1;i < n;i++)  {   if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) )   {    p0 = list[i];    k = i;   }  }  swap(list[k],list[0]);  sort(list+1,list+n,_cmp); if(n == 1)  {top = 1;Stack[0] = 0;return;}if(n == 2)  {   top = 2;   Stack[0] = 0;   Stack[1] = 1;   return ;  }  Stack[0] = 0;  Stack[1] = 1;  top = 2;  for(int i = 2;i < n;i++)  {   while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0)top--;   Stack[top++] = i;  }
}
Point tree[20];
int main() {int n;int kase = 1;while(~scanf("%d", &n), n) {printf("Forest %d\n", kase++);int i, j;for(i = 0; i < n; i++) {scanf("%lf %lf %lf %lf", &tree[i].x, &tree[i].y, &tree[i].v, &tree[i].l);}double ansc = 10000000, ansl;int anst[20];int num = 0;for(i = 0; i < 1 << n; i++) {int cnt = 0;double len1 = 0, len2 = 0, cost = 0;for(j = 0; j < n; j++) {if(i >> j & 1) {list[cnt++] = tree[j];}else {len2 += tree[j].l;cost += tree[j].v;}}if(cnt == 0) continue;  //砍0棵树 Graham(cnt);for(j = 0; j < top; j++) {len1 += dist(list[Stack[j]], list[Stack[(j + 1) % top]]);}if(len1 <= len2) {if(ansc > cost) {ansc = cost;ansl = len2 - len1;num = 0;for(j = 0; j < n; j++) {if(!(i >> j & 1)) {anst[num++] = j;}}}else if(ansc == cost){if(n - cnt < num) {ansc = cost;ansl = len2 - len1;num = 0;for(j = 0; j < n; j++) {if(i >> j & 1) {anst[num++] = j;}}}}}}printf("Cut these trees:");for(i = 0; i < num; i++) {printf(" %d", anst[i] + 1);}printf("\n");printf("Extra wood: ");printf("%.2lf\n\n", ansl);}return 0;
}

POJ 1873 The Fortified Forest (凸包,状态压缩枚举)相关推荐

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

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

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

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

  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 题目大意: 给你n棵树每棵树的坐标,高度,价值,要求砍掉一些树,用那些木材,将其它树围起来,要求花最小的代价,代价相同,要求砍掉最少的树. ...

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

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

  6. ●POJ 1873 The Fortified Forest

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

  7. LeetCode 2002. 两个回文子序列长度的最大乘积(状态压缩+枚举状态子集+预处理)

    文章目录 1. 题目 2. 解题 2.1 超时 2.2 预处理优化 1. 题目 给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 . 两个子序列在原字符串中如果 ...

  8. LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)

    文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...

  9. 【poj】1873: The Fortified Forest (凸包+状态压缩+各种搞事)

    题目描述: The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7818   Accep ...

最新文章

  1. C# http 性能优化500毫秒到 60 毫秒
  2. springmvc xml 空模板
  3. android实现分类搜索功能,android应用中的搜索功能怎么实现的
  4. Linux命令技巧之30个必会的命令技巧
  5. 黑马程序员pink老师前端入门教程,零基础必看的JavaScript基础语法视频教程(一)
  6. 编程打怪升级之路2018-06-01
  7. Little Sub and Traveling
  8. 时间序列研(part1)--随机过程
  9. React 是怎样炼成的
  10. bat 变量 文件内容第一行_VBA基础入门(38)FSO生成bat文件后执行的实例
  11. python selenium 进入新标签页_python 爬虫之selenium可视化爬虫
  12. 【报告分享】2021新茶饮研究报告.pdf(附下载链接)
  13. 你不知道的Bitmap
  14. java -jar 指定main,java打包成jar并执行jar包中指定的main方法
  15. laravel框架详解
  16. ie11安装程序无法继续 因为你的计算机,ie11无法安装解决方法详解
  17. 将Word中的表格以图片形式复制到微信发送
  18. IE11 error object doesn't support property or method 'fill'
  19. 本地python版GEE安装及配置步骤(jupyter lab)
  20. hadoop安装过程命令汇总

热门文章

  1. 大数据之jstorm,storm,hbase,hadoop and so on
  2. 【备忘】Linux上传文件,下载文件
  3. 常用Java技术社区
  4. 二叉堆--insert操作以及deleteMin操作的实现(C语言)
  5. 微信小程序动画(七):让页面动起来
  6. 麦芽糖-聚乙二醇-人血清白蛋白,HAS-PEG-maltose
  7. 第五篇:初识JVM,JVM自动内存管理
  8. 光子最大的游戏bug?刺激战场8倍镜秒变15倍镜竟如此简单?
  9. mc4 安卓x86_MC4 2D HD游戏下载|
  10. HBuilder mui入门教程——(1)简介