按位枚举,按最小价值,最小砍掉树剪枝就好了。
#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;
}