• poj1873(二进制枚举+求凸包周长)


    题目链接:https://vjudge.net/problem/POJ-1873

    题意:n个点(2<=n<=15),给出n个点的坐标(x,y)、价值v、做篱笆时的长度l,求选择哪些点来做篱笆围住另一些点,使得选出的这些点的价值和最小,如果价值和相等要求个数最小。

    思路:

      看来这是WF的签到题吧。数据很小,直接二进制枚举 (1<<n),然后对未选出的点求凸包的周长,仅当选出点的长度l的和>=凸包周长时才更新答案。

    AC code:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    const int maxn=20;
    const int inf=0x3f3f3f3f;
    
    struct Point{
        int x,y;
        Point():x(0),y(0){}
        Point(int x,int y):x(x),y(y){}
    };
    
    int n,cas,val,num,res[maxn],v[maxn],l[maxn],vis[maxn];
    double ext;
    int top,stack[maxn];
    Point pt[maxn],list[maxn];
    
    int cross(Point p0,Point p1,Point p2){
        return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
    }
    
    double dis(Point p1,Point p2){
        return sqrt((double)(p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
    }
    
    bool cmp(Point p1,Point p2){
        int tmp=cross(list[0],p1,p2);
        if(tmp>0) return true;
        else if(tmp==0&&dis(list[0],p1)<dis(list[0],p2)) return true;
        else return false;
    }
    
    void init(int m){
        Point p0=list[0];
        int k=0;    
        for(int i=1;i<m;++i){
            if((p0.y>list[i].y)||((p0.y==list[i].y)&&(p0.x>list[i].x))){
                p0=list[i];
                k=i;
            }
        }
        list[k]=list[0];
        list[0]=p0;
        sort(list+1,list+m,cmp);
    }
    
    double graham(int m){
        if(m==1){
            top=0;
            stack[0]=0;
        }
        else{
            top=1;
            stack[0]=0;
            stack[1]=1;
            for(int i=2;i<m;++i){
                while(top>0&&cross(list[stack[top-1]],list[stack[top]],list[i])<=0) --top;
                stack[++top]=i;
            }
        }
        double ret=0;
        for(int i=0;i<top;++i)
            ret+=dis(list[stack[i]],list[stack[i+1]]);
        ret+=dis(list[stack[top]],list[stack[0]]);
        return ret;
    }
    
    int main(){
        while(scanf("%d",&n),n){
            val=num=inf;
            for(int i=0;i<n;++i)
                scanf("%d%d%d%d",&pt[i].x,&pt[i].y,&v[i],&l[i]);
            for(int i=1;i<(1<<n)-1;++i){
                int t1=0,t2=0,cnt=0;
                for(int j=0;j<n;++j){
                    if((i>>j)&1){
                        t1+=v[j],t2+=l[j];
                    }
                    else{
                        list[cnt++]=pt[j];
                    }
                }
                init(cnt);
                int cnt2=n-cnt;
                if((t1<val)||((t1==val)&&(cnt2<num))){
                    double tmp=graham(cnt);
                    if(tmp>t2) continue;
                    val=t1,num=cnt2,ext=t2-tmp;
                    int t=0;
                    for(int j=0;j<n;++j){
                        if((i>>j)&1)
                            res[t++]=j;
                    }
                }
            }
            printf("Forest %d
    Cut these trees:",++cas);
            for(int i=0;i<num;++i)
                printf(" %d",res[i]+1);
            printf("
    Extra wood: %.2f
    
    ",ext);
        }
        return 0;
    }
  • 相关阅读:
    5-1 CSS命名规范
    npm
    Maven的安装与配置
    Emmet
    计算机常识——IP/TCP协议
    判别分析——距离判别
    R语言创建空向量、矩阵
    Rstudio——基本功能及操作
    R语言——source函数
    R语言关于warning问题——关于options函数
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11827130.html
Copyright © 2020-2023  润新知