poj1873(枚举+凸包)
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 7291 | Accepted: 2031 |
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.
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
Source
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#define zero(a) (fabs((double)(a))<(1e-8))
using namespace std;
const int eps=1e-8;
struct tr{
int x,y,v,l;
}s1[20],s[20];
int st[20];
int mul(tr p,tr u,tr v){//求叉积
return (p.x-u.x)*(v.y-u.y)-(v.x-u.x)*(p.y-u.y);
}
double dis(tr a,tr b){//求长度
return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(tr a,tr b){//极角排序
if(mul(a,s[0],b)>0)//以最小点s[0]为基准排序
return true;
else if(zero(mul(a,s[0],b))&&dis(s[0],a)<dis(s[0],b))
return true;
return false;
}
int mv,ct,nt;
double l2;
int do1(int n,int l1,int mv1,int c){
int i,j;
int x,y;
double l;//要用的木材长度
if(n==1){
l=0;
}
/*else if(n==2){
l=dis(s[0],s[1])*2;
}*/
else{
l=0;
for(i=1;i<n;i++){
if(s[0].y>s[i].y||(s[0].y==s[i].y&&s[0].x>s[i].x)){//将s[0]化为最小点,以便极角排序
swap(s[0],s[i]);
}
}
sort(s+1,s+n,cmp);//排序
int top,cnt;
st[0]=0;
st[1]=1;
tr a,b;
top=2;
cnt=2;
while(cnt<n-1){//当
st[top]=cnt;//先放入当前点
top++;
cnt++;
a=s[st[top-1]];
b=s[st[top-2]];
while(mul(s[cnt],a,b)<eps){//以当前点的下一个点为标杆点来除去不合凸包条件的点(Graham扫描法)(如果标杆点在当前栈顶的两个点组成的直线的右边,则说明栈顶的点不是凸包上的点)
top--;//去掉不合条件的点
a=b;//重新判断当前栈顶的点
b=s[st[top-2]];
}
}
st[top++]=n-1;//压入最后一次的标杆点,它一定是凸包上的点,因为它在最左边
for( i=0;i<top-1;i++){
l+=dis(s[st[i]],s[st[i+1]]);
}
l+=dis(s[0],s[n-1]);//把这句代码写成了l+=dis(s[st[0]],s[st[n-1]]),卡了三个小时,QAQ,引以为戒啊
}
//printf("%d %d\n",l1,l);
if((l1-l)>=0){// 砍掉的树可以把剩下的树围起来
if(mv1>mv){//剩下树的价值要最大
l2=l1-l;
nt=n;
mv=mv1;
ct=c;
}
else if(mv1==mv&&nt<=n){//价值相同时砍掉的树要最少
l2=l1-l;
nt=n;
mv=mv1;
ct=c;
}
}
return 0;
}
int main(){
int n,i,j,k=0;
int a,b,cnt,c;
int mv1;
while(scanf("%d",&n)!=EOF&&n){
k++;
nt=0;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&s1[i].x,&s1[i].y,&s1[i].v,&s1[i].l);
}
mv=0;
ct=0;
for(j=1;j<(1<<n)-1;j++){//二进制枚举
//printf("%d\n",j);
a=j,b=0;
cnt=0;
mv1=0;
int l1=0;
for(i=0;i<n;i++){
if(((1<<i)&j)){//按位与
s[cnt++]=s1[i];//放入不砍的树
mv1+=s1[i].v;//剩余的价值
}
else{
l1+=s1[i].l;//可以做篱笆的长度
}
}
if(mv>mv1)//剩下的价值小于最优的价值
continue;
do1(cnt,l1,mv1,j);
}
printf("Forest %d\n",k);
printf("Cut these trees:");
for(i=0;i<n;i++)
if(!((1<<i)&ct)) printf(" %d",i+1);
printf("\n");
printf("Extra wood: %.2f\n\n",l2);
}
return 0;
}
poj1873(枚举+凸包)的更多相关文章
- POJ 1873 The Fortified Forest(枚举+凸包)
Description Once upon a time, in a faraway land, there lived a king. This king owned a small collect ...
- POJ 3135 Polygons on the Grid(枚举+凸包)
题目大意是让你用这n条边放在网格上构成凸包,并且边的两端点必须在网格上. 那么比较容易想到的就是枚举可能情况,因为这样的勾股数组成情况不多,因此可以直接枚举所有连出去的边反映在坐标轴上的所有情况,最后 ...
- POJ 1873 - The Fortified Forest 凸包 + 搜索 模板
通过这道题发现了原来写凸包的一些不注意之处和一些错误..有些错误很要命.. 这题 N = 15 1 << 15 = 32768 直接枚举完全可行 卡在异常情况判断上很久,只有 顶点数 &g ...
- HDU 3685 Rotational Painting(多边形质心+凸包)(2010 Asia Hangzhou Regional Contest)
Problem Description Josh Lyman is a gifted painter. One of his great works is a glass painting. He c ...
- poj 2187 凸包加旋转卡壳算法
题目链接:http://poj.org/problem?id=2187 旋转卡壳算法:http://www.cppblog.com/staryjy/archive/2009/11/19/101412. ...
- (hdu step 7.1.5)Maple trees(凸包的最小半径寻找掩护轮)
称号: Maple trees Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...
- BZOJ2300[HAOI2011]防线修建——非旋转treap+凸包(平衡树动态维护凸包)
题目描述 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于 ...
- POJ 2187 - Beauty Contest - [凸包+旋转卡壳法][凸包的直径]
题目链接:http://poj.org/problem?id=2187 Time Limit: 3000MS Memory Limit: 65536K Description Bessie, Farm ...
- [hdu3685]Rotational Painting 凸包 重心
大致题意: 给出一个多边形,问你有多少种放法可以使得多边形稳定得立在平面上. 先对多边形求重心,在求凸包,枚举凸包的边,如果重心没有在边的范围内,则不行 判断是否在范围内可用点积来判断 #includ ...
随机推荐
- C#-----字节数组(byte[])和字符串相互转换
Encoding类 表示字符编码 1.字符串转换成字节数组byte[] using System; using System.Collections.Generic; using System ...
- thymeleaf 添加语法提示
thymeleaf 添加语法提示: xmlns:th="http://www.thymeleaf.org"
- 分配swap分区
1.free命令 用来查看swap分区的使用情况[root@localhost ~]#free#查看内存与swap分区使用状况◆cached(缓存):是指把读取出来的数据保存在内存当中,当再次 读取时 ...
- ansible常用命令大全
ansible 默认提供了很多模块来供我们使用.在 Linux 中,我们可以通过 ansible-doc -l 命令查看到当前 ansible 都支持哪些模块,通过 ansible-doc -s ...
- SQL Server 2012安装时报错,错误 0x80070422怎么解决?解决方法。
步骤一: Win+R打开运行窗口,输入services.msc 打开服务窗口 步骤二: 找到并启用"Windows Update" 成功进入下一步!
- EDK II之Device Path
UEFI中通过Device Path来描述设备的路径,一个完整的路径由多个Device Path Nodes组成. 下面通过输入设备的路径作为例子: PNP0A03 – PCI Host Bridge ...
- shell批量修改mysql用户密码
需求 现在有这么一个需求, 需要大批量修改用户的密码, 需要注意的规则是: 必须添加的字符: *$#sjdKw% 用户名的第一位+*$#sjdKw%+用户名的最后一位,比如用户名chenglee,密码 ...
- P3829 [SHOI2012]信用卡凸包
思路 注意到结果就是每个信用卡边上的四个圆心的凸包周长+一个圆的周长 然后就好做了 注意平行时把距离小的排在前面,栈中至少要有1个元素(top>1),凸包中如果存在叉积为0的点也要pop,否则可 ...
- Learning-Python【9】:Python文件操作
1.什么是文件 文件是操作系统提供给用户或应用程序的一种虚拟单位,该虚拟单位直接映射的是硬盘空间.通俗点说,文件就是存放数据的地方 2.为何要处理文件 用户或应用程序直接操作文件(读/写)就被操作系统 ...
- WebApi 后台获取token值
前台传递一个token,后台不知道怎么获取那么不是很悲剧吗. $(function () { $.ajax({ url: "/api/TokensTest/FirstCode", ...