●POJ 1873 The Fortified Forest

题链:

http://poj.org/problem?id=1873

题解:

计算几何,凸包

枚举被砍的树的集合。求出剩下点的凸包。然后判断即可。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=16,INF=0x3f3f3f3f;
const double eps=1e-8;
int sign(double x){
	if(fabs(x)<=eps) return 0;
	return x<0?-1:1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	void Read(){scanf("%lf%lf",&x,&y);}
}D[MAXN],H[MAXN];
typedef Point Vector;
bool operator < (Point A,Point B){return sign(A.x-B.x)<0||(sign(A.x-B.x)==0&&sign(A.y-B.y)<0);}
bool operator == (Point A,Point B){return sign(A.x-B.x)==0&&sign(A.y-B.y)==0;}
Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);}
double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;}
double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;}
int V[MAXN],N,ansS,ansV,ansN;
double L[MAXN],resL;
double GL(Vector A){//Get_Length
	return sqrt(A*A);
}
int Andrew(int S){
	int hnt=0,k=0,tnt=0;
	static Point tmp[MAXN];
	for(int i=1;i<=N;i++) if(!(S&(1<<(i-1)))) tmp[++tnt]=D[i];
	sort(tmp+1,tmp+tnt+1);
	tnt=unique(tmp+1,tmp+tnt+1)-tmp-1;
	for(int i=1;i<=tnt;i++){
		while(hnt>1&&sign((H[hnt]-H[hnt-1])^(tmp[i]-H[hnt-1]))<=0) hnt--;
		H[++hnt]=tmp[i];
	} k=hnt;
	for(int i=tnt-1;i>=1;i--){
		while(hnt>k&&sign((H[hnt]-H[hnt-1])^(tmp[i]-H[hnt-1]))<=0) hnt--;
		H[++hnt]=tmp[i];
	}
	return hnt;
}
double GCPC(int hnt){//Get_Convex_Polygon_Circumference	
	double C=0;
	for(int i=1;i<hnt;i++) C+=GL(H[i+1]-H[i]);
	return C;
}
int main(){
	double C,nowL;
	int nowS,nowV,nowN,Case=0;
	while(scanf("%d",&N)&&N){
		if(N==0) break;
		ansS=(1<<N)-1; ansV=INF; ansN=N; resL=0;
		for(int i=1;i<=N;i++)
			D[i].Read(),scanf("%d%lf",&V[i],&L[i]);
		for(int S=1;S<=(1<<N)-1;S++){
			nowS=S; nowN=0; nowL=0; nowV=0;
			for(int i=1;i<=N;i++) if(S&(1<<(i-1)))
				nowN++,nowV+=V[i],nowL+=L[i];
			C=GCPC(Andrew(S));
			if(sign(nowL-C)<0) continue;
			if(nowV<ansV||(nowV==ansV&&nowN<ansN))
				ansS=nowS,ansV=nowV,ansN=nowN,resL=nowL-C;
		}
		if (Case) puts(""); 		
		printf("Forest %d
",++Case);
		printf("Cut these trees:");
		for(int i=1;i<=N;i++) if(ansS&(1<<(i-1))) printf(" %d",i);
		printf("
Extra wood: %.2lf
",resL);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zj75211/p/8227646.html