POJ 1873 The Fortified Forest(枚举+凸包)
Description
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 ends with an empty test case (n = 0).
Output
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了好几次啊……
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; const double EPS = 1e-; inline int sgn(const double &x) {
if(fabs(x) < EPS) return ;
return x > ? : -;
} struct Point {
double x, y;
int v, l;
}; inline bool Cross(Point &sp, Point &ep, Point &op) {
return (sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y) >= ;
} inline double dist(Point &a, Point &b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
} inline bool cmp(const Point &a, const Point &b) {
if(a.y == b.y) return a.x < b.x;
return a.y < b.y;
} const int MAXN = ;
int stk[MAXN];
bool cut[MAXN], ans[MAXN];
Point p[MAXN], a[MAXN];
int n, top;
double answood; double Graham_scan(int n) {
sort(p, p + n, cmp);
top = ;
stk[] = ; stk[] = ;
for(int i = ; i < n; ++i) {
while(top && Cross(p[i], p[stk[top]], p[stk[top - ]])) --top;
stk[++top] = i;
}
int len = top;
stk[++top] = n - ;
for(int i = n - ; i >= ; --i) {
while(top != len && Cross(p[i], p[stk[top]], p[stk[top - ]])) --top;
stk[++top] = i;
}
double sum = ;
stk[++top] = stk[];
for(int i = ; i < top; ++i)
sum += dist(p[stk[i]], p[stk[i+]]);
return sum;
} int minval, mincut, sumval, sumlen;
double uselen; void setans(int cutcnt) {
for(int i = ; i <= n; ++i) ans[i] = cut[i];
minval = sumval;
mincut = cutcnt;
answood = sumlen - uselen;
} void dfs(int dep, int cutcnt) {
if(dep == n + ) {
if(n == cutcnt) return ;
sumval = sumlen = ;
for(int i = ; i <= n; ++i) {
if(!cut[i]) continue;
sumval += a[i].v;
sumlen += a[i].l;
}
if(sumval > minval) return ;
if(sumval == minval && cutcnt >= mincut) return ;
if(n - cutcnt == ) {
uselen = ;
setans(cutcnt);
}
else if(n - cutcnt == ) {
int i1 = , i2 = ;
for(int i = ; i <= n; ++i) {
if(cut[i]) continue;
if(!i1) i1 = i;
else i2 = i;
}
uselen = * dist(a[i1], a[i2]);
if(uselen <= sumlen) setans(cutcnt);
}
else {
int pcnt = ;
for(int i = ; i <= n; ++i) {
if(cut[i]) continue;
p[pcnt++] = a[i];
}
uselen = Graham_scan(pcnt);
if(sgn(uselen - sumlen) <= ) setans(cutcnt);
}
return ;
}
cut[dep] = false;
dfs(dep + , cutcnt);
cut[dep] = true;
dfs(dep + , cutcnt + );
} int main() {
int ca = ;
while(scanf("%d", &n) != EOF && n) {
for(int i = ; i <= n; ++i) {
scanf("%lf%lf%d%d", &a[i].x, &a[i].y, &a[i].v, &a[i].l);
}
mincut = MAXN;
minval = 0x7fffffff;
dfs(, );
if(ca != ) printf("\n");
printf("Forest %d\n", ca++);
printf("Cut these trees:");
for(int i = ; i <= n; ++i) if(ans[i]) printf(" %d", i);
printf("\nExtra wood: %.2f\n", answood);
}
}
POJ 1873 The Fortified Forest(枚举+凸包)的更多相关文章
- POJ 1873 The Fortified Forest(凸包)题解
题意:二维平面有一堆点,每个点有价值v和删掉这个点能得到的长度l,问你删掉最少的价值能把剩余点围起来,价值一样求删掉的点最少 思路:n<=15,那么直接遍历2^15,判断每种情况.这里要优化一下 ...
- POJ 1873 The Fortified Forest [凸包 枚举]
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6400 Accepted: 1 ...
- ●POJ 1873 The Fortified Forest
题链: http://poj.org/problem?id=1873 题解: 计算几何,凸包 枚举被砍的树的集合.求出剩下点的凸包.然后判断即可. 代码: #include<cmath> ...
- POJ 1873 The Fortified Forest
题意:是有n棵树,每棵的坐标,价值和长度已知,要砍掉若干根,用他们围住其他树,问损失价值最小的情况下又要长度足够围住其他树,砍掉哪些树.. 思路:先求要砍掉的哪些树,在求剩下的树求凸包,在判是否可行. ...
- 简单几何(凸包+枚举) POJ 1873 The Fortified Forest
题目传送门 题意:砍掉一些树,用它们做成篱笆把剩余的树围起来,问最小价值 分析:数据量不大,考虑状态压缩暴力枚举,求凸包以及计算凸包长度.虽说是水题,毕竟是final,自己状压的最大情况写错了,而且忘 ...
- POJ 1873 The Fortified Forest 凸包 二进制枚举
n最大15,二进制枚举不会超时.枚举不被砍掉的树,然后求凸包 #include<stdio.h> #include<math.h> #include<algorithm& ...
- POJ 1873 - The Fortified Forest 凸包 + 搜索 模板
通过这道题发现了原来写凸包的一些不注意之处和一些错误..有些错误很要命.. 这题 N = 15 1 << 15 = 32768 直接枚举完全可行 卡在异常情况判断上很久,只有 顶点数 &g ...
- poj 1873 凸包+枚举
The Fortified Forest Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 6198 Accepted: 1 ...
- poj1873 The Fortified Forest 凸包+枚举 水题
/* poj1873 The Fortified Forest 凸包+枚举 水题 用小树林的木头给小树林围一个围墙 每棵树都有价值 求消耗价值最低的做法,输出被砍伐的树的编号和剩余的木料 若砍伐价值相 ...
随机推荐
- oracle入门(一)
### 一.体系结构 1. 数据库 : 只有一个数据库 2. 实例 : 后台运行的一个进程 3. 表空间: 逻辑存储单位 4. 数据文件: 物理存储单位 5. 用户:面向用户管理,由用户来管理表空间, ...
- JQuery的焦点事件focus() 与按键事件keydown() 及js判断当前页面是否为顶级页面 子页面刷新将顶级页面刷新 window.top.location
相关代码如下,使用看注解 <script type="text/javascript"> if(window.self != window.top){ window.t ...
- 洛谷P3812 【模板】线性基
题目背景 这是一道模板题. 题目描述 给定n个整数(数字可能重复),求在这些数中选取任意个,使得他们的异或和最大. 输入输出格式 输入格式: 第一行一个数n,表示元素个数 接下来一行n个数 输出格式: ...
- 在Java中用正则表达式判断一个字符串是否是数字的方法
package chengyujia; import java.util.regex.Pattern; public class NumberUtil { /** * 判断一个字符串是否是数字. * ...
- jQuery实现 自动滚屏操作
实现自动滚屏思路: 1.滚屏即:文本的往上移动一段距离: 2.那么我们使文本每过一段时间就往上移动一段固定距离,就可实现滚屏: 3.直到文本底部出现在浏览器窗口中,专业点就是 文本移动的距离 + 浏览 ...
- double工具类
package com.zq.utils; /** * * 经度数字操作类 * * Created by MyEclipse. Author: ChenBin E-mail: chenbin_2008 ...
- 【rabbitmq消息队列配置】
#erlang语言支持包 #rabbitmq-server安装支持 #添加用户 #删除用户 #用户角色 #启动 #登录 #管理界面 #guest登录不了: Rabbitmq.conf文件添加 #开启管 ...
- yii学习笔记(3),自定义全局工具函数
在平时开发是经常需要打印数据来调试 常见的打印方式有print_r和var_dump,但是这样打印出来格式很乱不好浏览 在打印函数前后加上<pre></pre>就可以将内容原样 ...
- consonant_摩擦音
consonant_摩擦音_[t∫].[dʒ].[tr].[dr].[ts].[dz] 破擦音:即有爆破音又有摩擦音. [t∫]:噘嘴,舌尖抵住上牙龈,舌头下切,用一瞬间的气流发出声音,不震动. ch ...
- python之内存与编码的那点事
一.初始编码 ASCII 码不支持中文 是py2版本中的默认编码 Unicode 万国码, 英文使用16位(即两个字节),中文使用32位(四个字节) utf-8 美国最少使用八位(1字节), 欧 ...