●POJ 1873 The Fortified Forest

时间:2023-03-08 20:28:42

题链:

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\n",++Case);
printf("Cut these trees:");
for(int i=1;i<=N;i++) if(ansS&(1<<(i-1))) printf(" %d",i);
printf("\nExtra wood: %.2lf\n",resL);
}
return 0;
}