poj 1873The Fortified Forest (凸包 二进制枚举)

来源:互联网 发布:湖南棋牌app源码 编辑:程序博客网 时间:2024/05/15 12:21

注意:

一共n位,所以i从1枚举到 (1<

#include <iostream>#include <cmath>#include <cstdio>#include <string.h>#include <algorithm>#define pi acos(-1)#define eps 1e-8using namespace std;struct point{    double x,y,v,len;    int num;    point(){}    point(double xx,double yy){x=xx,y=yy;}    double operator * (point t){        return x*t.y - t.x*y;    }    point operator - (point t){        return point(x-t.x,y-t.y);    }}a[20],b[20];bool cmp(point a,point b){    return a.x < b.x;}double dis(point a,point b){    return sqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) );}point stak[1000];int vis[200],needv;double sumlen = 0,needlen = 0;double graham(int n){    for(int i = 1;i <= n;i++){        b[i] = a[i];    }    sort(b+1, b+1+n,cmp);    int r,top=0,m;    for(int i = 1; i <= n; i++) {        if(vis[ b[i].num ] == 1) continue;        while(top>1 && (stak[top]-stak[top-1])*(b[i]-stak[top]) <= 0 ) top--;        stak[++top] = b[i];    }    m = top;    for(int i = n-1; i >= 1; i--) {        if(vis[b[i].num] == 1) continue;        while(top>m && (stak[top]-stak[top-1])*(b[i]-stak[top]) <= 0 ) top--;        stak[++top] = b[i];    }    for(int i = 2;i<=top;i++){        needlen += dis(stak[i],stak[i-1]);    }    return needlen;}int  f(int i){    memset(vis,0,sizeof(vis));    sumlen = 0,needlen = 0,needv=0;    int cnt = 0;    for(int j = 1;i != 0;i>>=1,j++){        if(i&1){            vis[j] = 1;            sumlen += a[j].len;cnt++;            needv += a[j].v;        }    }    return cnt;}int main(){    int n,l,ncase=0;    while(~scanf("%d",&n),n){        ncase++;        for(int i = 1;i <= n;i++){            scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&a[i].v,&a[i].len);            a[i].num = i;        }        int delimiter = (1<<(n));        int ans = 100;        int ansi = 0,ansv = 0x3f3f3f3f;        for(int i = 1;i < delimiter;i++){            int cnt_del = f(i);            if(needv > ansv) continue;            graham(n);            if(needlen <= sumlen+eps && ansv > needv){                ans = cnt_del,ansi = i;ansv = needv;            }            else if(needlen <= sumlen+eps && ansv == needv && ans > cnt_del){                ansi = i;ans = cnt_del;            }        }        f(ansi);        graham(n);        printf("Forest %d\n",ncase);        printf("Cut these trees: ");        for(int i = 1;i <= n;i++){            if(vis[i] == 1)                printf("%d ",i);        }        puts("");        printf("Extra wood: %.2f\n\n",sumlen-needlen);    }    return 0;}
阅读全文
0 0