POJ 1873 The Fortified Forest (凸包,状态压缩枚举)
题目链接: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 (凸包,状态压缩枚举)相关推荐
- POJ 1873 The Fortified Forest 凸包 二进制枚举
n最大15,二进制枚举不会超时.枚举不被砍掉的树,然后求凸包 #include<stdio.h> #include<math.h> #include<algorithm& ...
- POJ 1873 The Fortified Forest(枚举+凸包+剪枝)
POJ 1873 The Fortified Forest 题意: 某王有一些树,要制作一个栅栏将所有树围起来,栅栏制作木材来源就是砍去其中一些树. 现在输入每棵树的坐标,价值,高度,求出所围价值最大 ...
- poj 1873 The Fortified Forest (位运算枚举 + 凸包周长)
题目链接:http://poj.org/problem?id=1873 大意:有一片N棵树的森林,要从中砍掉几棵树做成篱笆,把剩下的树围起来 输入:给N课树,每棵树的坐标是x,y,每棵树有一个vi和l ...
- POJ 1873 The Fortified Forest(凸包)
http://poj.org/problem?id=1873 题目大意: 给你n棵树每棵树的坐标,高度,价值,要求砍掉一些树,用那些木材,将其它树围起来,要求花最小的代价,代价相同,要求砍掉最少的树. ...
- POJ 1873 The Fortified Forest(凸包)题解
题意:二维平面有一堆点,每个点有价值v和删掉这个点能得到的长度l,问你删掉最少的价值能把剩余点围起来,价值一样求删掉的点最少 思路:n<=15,那么直接遍历2^15,判断每种情况.这里要优化一下 ...
- ●POJ 1873 The Fortified Forest
题链: http://poj.org/problem?id=1873 题解: 计算几何,凸包 枚举被砍的树的集合.求出剩下点的凸包.然后判断即可. 代码: #include<cmath> ...
- LeetCode 2002. 两个回文子序列长度的最大乘积(状态压缩+枚举状态子集+预处理)
文章目录 1. 题目 2. 解题 2.1 超时 2.2 预处理优化 1. 题目 给你一个字符串 s ,请你找到 s 中两个 不相交回文子序列 ,使得它们长度的 乘积最大 . 两个子序列在原字符串中如果 ...
- LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
文章目录 1. 题目 2. 解题 1. 题目 外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧. 字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件, ...
- 【poj】1873: The Fortified Forest (凸包+状态压缩+各种搞事)
题目描述: The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 7818 Accep ...
最新文章
- C# http 性能优化500毫秒到 60 毫秒
- springmvc xml 空模板
- android实现分类搜索功能,android应用中的搜索功能怎么实现的
- Linux命令技巧之30个必会的命令技巧
- 黑马程序员pink老师前端入门教程,零基础必看的JavaScript基础语法视频教程(一)
- 编程打怪升级之路2018-06-01
- Little Sub and Traveling
- 时间序列研(part1)--随机过程
- React 是怎样炼成的
- bat 变量 文件内容第一行_VBA基础入门(38)FSO生成bat文件后执行的实例
- python selenium 进入新标签页_python 爬虫之selenium可视化爬虫
- 【报告分享】2021新茶饮研究报告.pdf(附下载链接)
- 你不知道的Bitmap
- java -jar 指定main,java打包成jar并执行jar包中指定的main方法
- laravel框架详解
- ie11安装程序无法继续 因为你的计算机,ie11无法安装解决方法详解
- 将Word中的表格以图片形式复制到微信发送
- IE11 error object doesn't support property or method 'fill'
- 本地python版GEE安装及配置步骤(jupyter lab)
- hadoop安装过程命令汇总
热门文章
- 大数据之jstorm,storm,hbase,hadoop and so on
- 【备忘】Linux上传文件,下载文件
- 常用Java技术社区
- 二叉堆--insert操作以及deleteMin操作的实现(C语言)
- 微信小程序动画(七):让页面动起来
- 麦芽糖-聚乙二醇-人血清白蛋白,HAS-PEG-maltose
- 第五篇:初识JVM,JVM自动内存管理
- 光子最大的游戏bug?刺激战场8倍镜秒变15倍镜竟如此简单?
- mc4 安卓x86_MC4 2D HD游戏下载|
- HBuilder mui入门教程——(1)简介