题目:
题意:
给出一些树(坐标,价值,长度),要求砍下一些树做成篱笆,将剩下的树围起来。求砍下的树最小价值的方案,如果有多种方案,输出砍的树的个数最少的。
题解:
嘛国王最多只有15棵树啊,dfs砍不砍的话2^15也不多,那就暴力一波,1A满意
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const double INF=1e18;
const int N=1005;
struct po
{
double x,y,v,l;
po(double X=0,double Y=0,double V=0,double L=0){x=X; y=Y; v=V; l=L;}
}dian[N],tree[N];
const double eps=1e-9;
int dcmp(double x)
{
if (x<=eps && x>=-eps) return 0;
return (x>0)?1:-1;
}
int n,top,stack[N],gs,nn;bool a[N],mb[N];double vv,ext;
po operator -(po x,po y){return po(x.x-y.x,x.y-y.y);}
double cj(po x,po y){return x.x*y.y-x.y*y.x;}
double len(po x,po y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
bool operator <(const po &x,const po &y){return (x.x<y.x)||(x.x==y.x && x.y<y.y);}
void tb()
{
gs=0;
for (int i=1;i<=n;i++)
if (!a[i]) dian[++gs]=tree[i];
sort(dian+1,dian+gs+1);
top=0;
for (int i=1;i<=gs;i++)
{
while (top>1 && dcmp(cj(dian[stack[top]]-dian[stack[top-1]],dian[i]-dian[stack[top-1]]))<=0) top--;
stack[++top]=i;
}
int k=top;
for (int i=gs-1;i>=1;i--)
{
while (top>k && dcmp(cj(dian[stack[top]]-dian[stack[top-1]],dian[i]-dian[stack[top-1]]))<=0) top--;
stack[++top]=i;
}
if (n>1) top--;
}
double need()
{
double ans=0;
for (int i=1;i<=top;i++)
ans+=len(dian[stack[i]],dian[stack[i%top+1]]);
return ans;
}
void dfs(int t,double value,double len,int num)
{
if (t>n)
{
tb();
double ee=len-need();
if (dcmp(ee)>=0 && (vv>value || (dcmp(vv-value)==0 && nn>num)))
{
vv=value;
nn=num;
for (int i=1;i<=n;i++) mb[i]=a[i];
ext=ee;
}
return;
}
for (int i=0;i<=1;i++)
a[t]=i,dfs(t+1,value+tree[t].v*i,len+tree[t].l*i,num+i);
}
int main()
{
int id=0;
while(scanf("%d",&n) && n)
{
double x,y,v,l;vv=INF;
for (int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x,&y,&v,&l);
tree[i]=po(x,y,v,l);
}
dfs(1,0,0,0);
printf("Forest %d\nCut these trees:",++id);
for (int i=1;i<=n;i++)
if (mb[i]) printf(" %d",i);
printf("\nExtra wood: %.2lf\n\n",ext);
}
}