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 ...
随机推荐
- matlab将rgb图转为灰度图的原理代码
MyYuanLaiPic = imread('e:/image/matlab/Cluo.jpg');%读取RGB格式的图像 MyFirstGrayPic = rgb2gray(MyYuanLaiPic ...
- MySQL外键约束_ON DELETE CASCADE/ON UPDATE CASCADE
MySQL通过外键约束实现数据库的参照完整性,外键约束条件可在创建外键时指定,table的存储引擎只能是InnoDB,因为只有这种存储模式才支持外键. 外键约束条件有以下4种: (1)restrict ...
- Python RabbitMQ 权重设置
消费端recv设置 注:设置消费端处理完一条消息后再发另一条 channel.basic_qos(prefetch_count=1) 由于每一条机器的处理速度不同,所以我们这里就会对应,机 ...
- Shell 脚本进阶2
1.查询系统基础情况脚本 #!/bin/bash # 系统状态查询脚本 # 输出系统基本信息 # # 系统版本 SYSTEM_VERSION=`cat /etc/redhat-release` # 主 ...
- 【题解】Luogu P4054 [JSOI2009]计数问题
原题传送门 我自闭了qaq 这道题非常简单,因为1<=c<=100,所以直接对每个c开二维树状数组,操作就跟模板一样 写码5分钟,调码半小时,这道题的输入顺序是x1,x2,y1,y2,我真 ...
- 数据库分区分表(sql、mysql)
http://blog.csdn.net/lgb934/article/details/8662956 http://www.2cto.com/database/201503/380348.html ...
- Linux下调试.Net core(1):lldb的安装
windows下,我们对于.net程序发生Crash,资源泄露,死锁等问题的分析,有神器windbg,那现在我们的.net core程序运行在linux上时,该怎么进行对对Core Dump文件进行分 ...
- P2292 [HNOI2004]L语言
传送门 思路: 毒瘤的字典树! ▲主要分有两个步骤: ① 日常的建树. ② 暴力地求解. ▲日常建树:过于基础,跳过. ▲重点在于如何暴力地求解而不被卡掉(DP?不存在的) 可以利用区间动规的思想, ...
- pandas 对象中 to_pickle 方法参数命名问题,不能用frame
这句话一直报错,经过反复排查,是命名问题,to_pickle() 参数不能是 frame,换一个名字就可以了 frame.to_pickle('examples\local_frame_pickle' ...
- scala模式匹配及样本类
样本类 1.带有case关键字的类被称为样本类: 例如:abstract class Expr case class Var(name: String) extends Expr case class ...