The Fortified Forest
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 6115   Accepted: 1720

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 <= n <= 15, the number of trees in the forest.
The trees are identified by consecutive integers 1 to n. Each of the
subsequent n lines contains 4 integers xi, yi, vi, li that describe a
single tree. (xi, yi) is the position of the tree in the plane, vi is
its value, and li 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

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

Sample Output

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

题意:国王有一些树,他想砍掉一些树做篱笆围住剩下的树,每棵树都有坐标,价值和做成篱笆长度,我们应该使砍掉的树的价值尽可能的小并且做成的篱笆能够围住剩下的树,如果方案的价值相同选择砍掉数量
少的,最后输出砍掉的树的编号和篱笆围了之后还能剩下多少。
题解:深坑啊。。。WA了好多次,竟然是cmp函数里面的变量p[0]的函数名冲突了...world final的水题都好难。。过,但是想法不难。。就是每次枚举那些树不取和取,不超过2^15次方,用二进制表示..然后再进行凸包。。比较。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const double eps = 1e-;
const int N = ;
struct Point
{
double x,y,value,len;
} p[N],q[N];
Point Stack[N];
int n;
double cross(Point a,Point b,Point c)
{
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
double dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
Point po; //大坑
int cmp(Point a,Point b)
{
if(cross(a,b,po)>) return ;
if(cross(a,b,po)==&&dis(b,po)-dis(a,po)>eps) return ;
return ;
}
double Graham(Point p[],int n)
{
if(n==||n==) return ;
if(n==) return *dis(p[],p[]);
int k =;
for(int i=; i<n; i++)
{
if(p[k].y>p[i].y||((p[k].y==p[i].y)&&(p[k].x>p[i].x))) k=i;
}
swap(p[],p[k]);
po = p[]; ///嗯,这里
int top=;
sort(p+,p+n,cmp);
Stack[]=p[];
Stack[]=p[];
Stack[]=p[];
for(int i=; i<n; i++)
{
while(top>=&&cross(p[i],Stack[top],Stack[top-])>=)
{
top--;
}
Stack[++top]=p[i];
}
double ans = ;
for(int i=; i<=top; i++)
{
ans+=dis(Stack[i],Stack[i-]);
}
ans+=dis(Stack[top],Stack[]);
return ans;
}
int main()
{
int _count = ;
while(scanf("%d",&n)!=EOF&&n)
{
for(int i=; i<n; i++)
{
scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&p[i].value,&p[i].len);
}
int t = (<<n)-;
int cnt[N],id[N];///保存要砍掉的树的编号
double save=;
int num=; ///要砍掉的数的数目
double mi=; ///保存要砍掉的树的最小价值
for(int i=; i<t; i++) ///1代表砍掉这棵树,0代表不砍,至少要砍一棵树
{
double value=,len=;
int k=,k1=;
for(int j=; j<n; j++)
{
if((i>>j)&) ///移位操作,表示当前第j+1棵树要砍掉
{
cnt[k++] = j;
value+=p[j].value;
len+=p[j].len;
}
else q[k1++] = p[j];
}
double L = Graham(q,k1);
if(len-L>eps) ///如果能够组成的篱笆长度大于凸包周长
{
if(mi-value>eps||(fabs(value-mi)<eps&&k<num))
{
mi = value;
for(int j=; j<k; j++) id[j]=cnt[j];
num = k;
save = len - L;
}
}
}
printf("Forest %d\nCut these trees: ",_count++);
for(int i=; i<num; i++)
{
printf("%d ",id[i]+);
}
printf("\nExtra wood: %.2lf\n\n",save);
}
return ;
}

poj 1873(枚举所有的状态+凸包)的更多相关文章

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

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

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

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

  3. poj 1873 凸包+枚举

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

  4. ●POJ 1873 The Fortified Forest

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

  5. poj - 3254 - Corn Fields (状态压缩)

    poj - 3254 - Corn Fields (状态压缩)超详细 参考了 @外出散步 的博客,在此基础上增加了说明 题意: 农夫有一块地,被划分为m行n列大小相等的格子,其中一些格子是可以放牧的( ...

  6. 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 ...

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

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

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

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

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

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

随机推荐

  1. hadoop集群之Datenode无法启动解决办法

    hadoop集群之Datenode无法启动解决办法 我们在启动hadoop集群的时候,通过jps查看进程,发现namenode RM和Secondary NameNode都有,但datanode没有启 ...

  2. Oracle exp,imp,expdp,impdp数据导入导出

    一.导出模式(三种模式)及命令格式 1. 全库模式 exp 用户名/密码@网络服务名 full=y file=路径\文件名.dmp log=路径\文件名.log 2. 用户模式(一般情况下采用此模式) ...

  3. erlang节点局域网通信

    节点1: F:\WorkSpace\Server\src>erl -name hw@192.168.10.142 -setcookie 4213 consulting .erlang in &q ...

  4. node express 登录拦截器 request接口请求

    1.拦截器 拦截器可以根据需要 做权限拦截 登录只是权限的一种, 思路是req.session.user判断用户session是否存在,是否是需要拦截的地址, 如果是就跳转登录页,或其他页, 如果非需 ...

  5. SQL面试题:之一(难度:中等)

    SQL面试题:之一(难度:中等)

  6. springboot注解使用,分页sql

    https://blog.csdn.net/KingBoyWorld/article/details/78948304

  7. 【转载】Unity插件研究院之自动保存场景

    原文: http://wiki.unity3d.com/index.php?title=AutoSave  最近发现Unity老有自动崩溃的BUG. 每次崩溃的时候由于项目没有保存所以Hierarch ...

  8. 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习

     孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...

  9. IPV4的地址是如何分类的?网络号的范围分别是多少?

    1. A类地址 (1)A类地址第1字节为网络地址,其它3个字节为主机地址. (2)A类地址范围:1.0.0.1—126.255.255.254 (3)A类地址中的私有地址和保留地址: ① 10.X.X ...

  10. 使用hadoop统计多个文本中每个单词数目

    程序源码 import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Con ...