POJ 1873

按位枚举,按最小价值,最小砍掉树剪枝就好了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;
const int MAXN=20;
const int inf=190000000;
int n,l;

int st[MAXN],stop,cnt;
int ans[MAXN];
bool cut[MAXN];
struct point{
	int x,y;
	int len,val;
	int num;
}p[MAXN];
int ansV,ansC;
double anslen;
bool cmp(point A,point B){
	if(A.y<B.y) return true;
	else if(A.y==B.y){
		if(A.x<B.x) return true;
	}
	return false;
}

bool cmp1(int a,int b){
	if(a<b) return true;
	return false;
}

bool multi(point a,point b,point c){
	return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x)<=0;
}

double dist(point a, point b){
	return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)*1.0);
}

double for_len(){
	if(cnt==1) return 0;
	double res=0;
	for(int i=1;i<cnt;i++)
	res+=dist(p[ans[i]],p[ans[i-1]]);
	return (res);
}

void slove(){
	stop=0; cnt=0;
	int choice=0; int be;
	for(int i=0;i<n;i++){
		if(!cut[i]){
			st[stop++]=i;
			choice++;
		}
		if(choice==2){
			be=i;
			break;
		}
	}
	if(choice<2){ cnt=1; return ; }
	for(int i=be+1;i<n;i++){
		if(cut[i]) continue;
		while(stop>1&&multi(p[st[stop-1]],p[i],p[st[stop-2]])) stop--;
		st[stop++]=i;
	}
	for(int i=0;i<stop;i++){
		ans[cnt++]=st[i];
	}
	stop=0; choice=0;
	for(int i=n-1;i>=0;i--){
		if(!cut[i]){
			st[stop++]=i;
			choice++;
		}
		if(choice==2){ be=i; break; }
	}
	for(int i=be-1;i>=0;i--){
		if(cut[i]) continue;
		while(stop>1&&multi(p[st[stop-1]],p[i],p[st[stop-2]])) stop--;
		st[stop++]=i;
	}
	for(int i=0;i<stop;i++)
	ans[cnt++]=st[i];
}

int main(){
	int cas=0;
	while(scanf("%d",&n)!=EOF){
		if(n==0) break;
		cas++;
		for(int i=0;i<n;i++){
			scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].val,&p[i].len);
			p[i].num=i+1;
		}
		sort(p,p+n,cmp);
		ansV=inf; int tmpV; int tmpC; double len; int CUT=inf;
		for(int i=1;i<(1<<n);i++){
			tmpV=0; tmpC=0; len=0;
			memset(cut,false,sizeof(cut));
			for(int k=0;k<n;k++){
				if((1<<k)&i){
					cut[k]=true;
					tmpV+=p[k].val;
					tmpC++;
					len+=p[k].len;
				}
			}
			if(tmpV<ansV){
				slove();
				double res=for_len();
				if(res<=len){
					CUT=tmpC;
					ansV=tmpV;
					ansC=i;
					anslen=len*1.0-res;
				}
			}
			else if(tmpV==ansV){
				if(CUT>tmpC){
					slove();
					double res=for_len();
					if(res<=len){
						CUT=tmpC;
						ansV=tmpV;
						ansC=i;
						anslen=len*1.0-res;
					}
				}
			}
		}
		printf("Forest %d\n",cas);
		printf("Cut these trees:");
		cnt=0;
		for(int k=0;k<n;k++)
		if((1<<k)&ansC){
			st[cnt++]=p[k].num;
		}
		sort(st,st+cnt,cmp1);
		for(int i=0;i<cnt;i++)
		printf(" %d",st[i]);
		printf("\n");
		printf("Extra wood: %0.2lf\n",anslen);
		printf("\n");
	}
	return 0;
}

  

POJ 1873,布布扣,bubuko.com

时间: 2024-10-12 23:52:06

POJ 1873的相关文章

poj 1873 凸包+枚举

The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6198   Accepted: 1744 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

POJ 1873 The Fortified Forest(凸包+枚举 World Finals 1999啊)

题目链接:http://poj.org/problem?id=1873 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 fr

Poj 1873 The Fortified Forest

地址:http://poj.org/problem?id=1873 题目: The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6421   Accepted: 1811 Description Once upon a time, in a faraway land, there lived a king. This king owned a small collection of r

poj 1873(枚举所有的状态+凸包)

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

POJ 1873 - The Fortified Forest 凸包 + 搜索 模板

通过这道题发现了原来写凸包的一些不注意之处和一些错误..有些错误很要命.. 这题 N = 15 1 << 15 = 32768 直接枚举完全可行 卡在异常情况判断上很久,只有 顶点数 >= 2,即 n >= 3 时凸包才有意义 顶点数为 1 时,tmp = - 1 要做特殊判断. 总结了一下凸包模板 //template Convex Hull friend bool operator < (const point &p1, const point &p2){

poj 1873 The Fortified Forest(凸包)

The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 5737   Accepted: 1636 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

POJ 1873 计算几何

思路: 二进制枚举一下要删哪些点 求个凸包,算一下贡献 //By SiriusRen #include <cmath> #include <cstdio> #include <algorithm> using namespace std; #define eps 1e-9 int n,cases,top,tot,k,rem,ansrem,ans; double length,tempdis,wei,answei,remwei; struct Tree{double x,

[转] POJ几何分类

转自:http://blog.csdn.net/tyger/article/details/4480029 计算几何题的特点与做题要领:1.大部分不会很难,少部分题目思路很巧妙2.做计算几何题目,模板很重要,模板必须高度可靠.3.要注意代码的组织,因为计算几何的题目很容易上两百行代码,里面大部分是模板.如果代码一片混乱,那么会严重影响做题正确率.4.注意精度控制.5.能用整数的地方尽量用整数,要想到扩大数据的方法(扩大一倍,或扩大sqrt2).因为整数不用考虑浮点误差,而且运算比浮点快. 一.点

【转】计算几何题目推荐

打算转下来好好做计算几何了. 原文地址:http://blog.sina.com.cn/s/blog_49c5866c0100f3om.html 其实也谈不上推荐,只是自己做过的题目而已,甚至有的题目尚未AC,让在挣扎中.之所以推荐计算几何题,是因为,本人感觉ACM各种算法中计算几何算是比较实际的算法,在很多领域有着重要的用途计算几何题的特点与做题要领:1.大部分不会很难,少部分题目思路很巧妙2.做计算几何题目,模板很重要,模板必须高度可靠.3.要注意代码的组织,因为计算几何的题目很容易上两百行