• 凸包 poj 1873


    我竟然A了 worldfinal 的水题

    n<=15

    所以可以列举每一种情况

    状态压缩

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    #include<stack>
    #include<math.h>
    
    using namespace std;
    
    #define MAXN 20
    #define INF 100000000
    class point
    {
    public:
        int x,y,v,len;
        int operator ^(point b)
        {
           return x*b.y-y*b.x;
        }
        point operator -(point b)
        {
            point c;
            c.x=x-b.x;
            c.y=y-b.y;
            return c;
        }
    }x[MAXN],res[MAXN],tur[MAXN];
    int ans,cut_len,MIN_val,MIN_CNT;
    double left;
    
    double Dis(point p1,point p2)
    {
        return sqrt(double((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
    }
    bool cmp(point a,point b)
    {
        int tmp=((a-res[0])^(b-res[0]));
        if(tmp>0)
            return 1;
        if(tmp==0&&Dis(a,res[0])<Dis(b,res[0]))
            return 1;
        return 0;
    }
    stack<point>s;
    
    double tubao(int num)
    {
    
        if(num==0)//这3个特判
            return 0;
        if(num==1)
            return 0;
        if(num==2)
            return 2*Dis(res[0],res[1]);
        int k=0; //扫描法 凸包
        for(int i=1;i<num;i++)
            if(res[i].y<res[k].y)
                k=i;
            else if(res[i].y==res[k].y&&res[i].x<res[k].x)
                k=i;
    
        swap(res[0],res[k]);
    
        sort(res+1,res+num,cmp);
        while(!s.empty())
            s.pop();
        s.push(res[0]);
        s.push(res[1]);
        point a,b;
    
        for(int i=2;i<num;i++)
        {
            b=s.top();
            s.pop();
            a=s.top();
            while(s.size()>1&&((res[i]-b)^(b-a))>=0)
            {
                b=a;
                s.pop();
                a=s.top();
            }
            s.push(b);
            s.push(res[i]);
        }
    
        int len=0;
        while(!s.empty())
        {
            tur[len++]=s.top();
            s.pop();
    
        }
        double dis=0;
        for(int i=0;i<len-1;i++)
            dis+=Dis(tur[i],tur[i+1]);
        dis+=Dis(tur[len-1],tur[0]);
        return dis;
    }
    int main()
    {
        int n,ca;
        ca=1;
    
        while(scanf("%d",&n)!=EOF&&n)
        {
            if(ca!=1)
                printf("
    ");
            for(int i=0;i<n;i++)
                scanf("%d%d%d%d",&x[i].x,&x[i].y,&x[i].v,&x[i].len);
            int ed=1<<n;
            MIN_CNT=MIN_val=INF;
            for(int i=0;i<ed;i++)//列举每一种情况
            {
                int cnt=0,num=0,val=0;
                double cut=0;
    
                for(int j=0;j<n;j++)
                    if(i&(1<<j))
                    {
                        cnt++;
                        cut+=x[j].len;
                        val+=x[j].v;
                    }
                    else
                    {
                        res[num++]=x[j];
                    }
    
                double dis=tubao(num);
    
                if(dis>cut)
                    continue;
                if(val<MIN_val||val==MIN_val&&cnt<MIN_CNT)//维护失去权值最小
                {
                    ans=i;
                    MIN_val=val;
                    MIN_CNT=cnt;
                    left=cut-dis;
                }
    
            }
            printf("Forest %d
    ", ca++);
            printf("Cut these trees:");
            for(int i=0;i<n;i++)
                if(ans&(1<<i))
                    printf(" %d",i+1);
            printf("
    Extra wood: %.2lf
    ",left);
        }
    
        return 0;
    }
  • 相关阅读:
    使用C#开发ActiveX控件 并制作Cab包
    asp.net后台创建table设置宽度百分比
    Sql按姓名查出某个人的成绩排名
    获得DataGridView多选框值
    解决iframe窗体丢失Session时登录窗口显示在子页面的问题
    xml返回数组数据
    安卓界面组件文本框
    安卓的UI界面开发(初学者推荐)
    安卓布局
    安卓界面组件按钮
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6284760.html
Copyright © 2020-2023  润新知