题意:砍掉一些树,用来围剩下的树,要使能包围的请款下,剩下树的价值最大,
思路:二进制枚举所有可能的情况,用凸包找包围的最短长度。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
using namespace std;
const int N = 19;
const double EPS = 1e-12;
struct cpoint{
double x,y;
int I;
double len,val;
void get(){scanf("%lf%lf%lf%lf",&x,&y,&val,&len);}
cpoint(double a,double b){x=a,y=b;}
cpoint(){}
bool operator<(const cpoint t) const{
return y<t.y||(y==t.y&&x<t.x);
}
};
double dist(cpoint a,cpoint b){
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double x_mult(cpoint a,cpoint b,cpoint c){
return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
int n;
int cmp(const cpoint a,const cpoint b){
return a.y<b.y||(a.y==b.y&&a.x<b.x);
}
cpoint re[N],tu[N];
int tmp[N];
double ans ,relen, Val;
int tans;
bool visit[N];
int granham(cpoint p[],int s,cpoint r[]){
int i,len,top=1;
sort(p,p+s,cmp);
r[0] = p[0];r[1] = p[1];r[2] = p[2];
if(s<3) return s;
for(i=2;i<s;i++){
while(top&&x_mult(p[i],r[top],r[top-1])>EPS) top--;
r[++top] = p[i];
}
len = top;r[++top] = p[s-2];
for(i=s-3;i>=0;i--){
while(top!=len&&x_mult(p[i],r[top],r[top-1])>EPS) top--;
r[++top] = p[i];
}
return top;
}
void solve(int m)
{
memset(visit,0,sizeof(visit));
double ret=0;
int trees=0,cnt=0;
relen = 0;
cpoint p[N];
for(int i=0;i<n;i++)
if(m&(1<<i))
{
visit[i] = true;
relen +=re[i].len;
trees++;
}else p[cnt++] = re[i],ret+=re[i].val;
int k = granham(p,cnt,tu);
double c=0;
if(k==2)
c=2*dist(tu[0],tu[1]);
else if(k<=1)
c = 0;
else
for(int i=0;i<k;i++)
c+=dist(tu[i],tu[i+1]);
if(relen>=c)
{
if(Val<ret)
{
Val=ret;
ans = relen-c;
tans = trees;
int k=0;
for(int i=0;i<n;i++)
if(visit[i]) tmp[k++] = re[i].I;
}
}
}
int main()
{
freopen("in.txt","r",stdin);
int T = 1;
while(~scanf("%d",&n)&&n)
{
Val = -1;
for(int i=0;i<n;i++) re[i].get(),re[i].I = i+1;
sort(re,re+n);
ans = 1e20;tans = 100;
for(int i=0;i<(1<<n);i++)
solve(i);
printf("Forest %d\n",T++);
printf("Cut these trees:");
sort(tmp,tmp+tans);
for(int i=0;i<tans;i++) printf(" %d",tmp[i]);
printf("\n");
printf("Extra wood: %.2lf\n\n",ans);
}
return 0;
}
本文介绍了一种通过二进制枚举和凸包算法确定最佳树木保留方案的方法,旨在最大化剩余树木的价值,同时确保被砍伐树木形成的围栏足够长以包围剩余的树木。

979

被折叠的 条评论
为什么被折叠?



