• 51nod 1392 装盒子


    有n个长方形盒子,第i个长度为Li,宽度为Wi,我们需要把他们套放。注意一个盒子只可以套入长和宽分别不小于它的盒子,并且一个盒子里最多只能直接装入另外一个盒子 (但是可以不断嵌套),例如1 * 1 可以套入2 * 1,而2 * 1再套入2 * 2。套入之后盒子占地面积是最外面盒子的占地面积。给定N个盒子大小,求最终最小的总占地面积。
    Input
    第一行一个数N表示盒子的个数。
    接下来N行,每行两个正整数,表示每个盒子的长度和宽度。
    所有整数都是正的(N,以及盒子的长宽),且不超过200。
    Output
    一行一个整数表示最终最小的占地面积。

    对于相同大小的盒子可以相互嵌套而只保留一个,考虑最大费用最大流,每个盒子i拆成a[i],b[i]两点,若x可放入y,则连边a[x]->b[y],流量1,费用为x的面积,代表x放入y对答案的影响,源点到a[i]连边,流量1,费用0,使每个盒子最多只能放进一个盒子,a[i],b[i]到汇点连边,流量1,费用0,使每个盒子最多只能被放入一个盒子

    #include<cstdio>
    #include<queue>
    #include<algorithm>
    int n;
    struct pos{
        int a,b;
    }ps[207];
    bool operator<(pos a,pos b){
        return a.a!=b.a?a.a<b.a:a.b<b.b;
    }
    bool operator==(pos a,pos b){
        return a.a==b.a&&a.b==b.b;
    }
    const int N=400007,inf=0x3f3f3f3f;
    int es[N],enx[N],ev[N],ec[N],e0[N],ep=2,S,T,ans=0,l[N],in[N],pv[N],pe[N];
    std::queue<int>q;
    void adde(int a,int b,int f,int c){
        es[ep]=b;enx[ep]=e0[a];ev[ep]=f;ec[ep]=c;e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];ev[ep]=0;ec[ep]=-c;e0[b]=ep++;
    }
    bool sp(){
        for(int i=1;i<=T;++i)l[i]=-inf;
        l[S]=0;
        q.push(S);
        while(!q.empty()){
            int w=q.front();q.pop();
            in[w]=0;
            for(int i=e0[w];i;i=enx[i])if(ev[i]){
                int u=es[i];
                if(l[w]+ec[i]>l[u]){
                    l[u]=l[w]+ec[i];
                    pv[u]=w;
                    pe[u]=i;
                    if(!in[u])in[u]=1,q.push(u);
                }
            }
        }
        return l[T]>0;
    }
    void mcs(){
        for(int w=T;w!=S;w=pv[w]){
            int e=pe[w];
            --ev[e];
            ++ev[e^1];
        }
        ans-=l[T];
    }
    int cs[2000];
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;++i)scanf("%d%d",&ps[i].a,&ps[i].b);
        std::sort(ps,ps+n);
        n=std::unique(ps,ps+n)-ps;
        S=n*2+1;T=S+1;
        for(int i=0;i<n;++i){
            ans+=ps[i].a*ps[i].b;
            for(int j=0;j<n;j++)if(i!=j&&ps[i].a<=ps[j].a&&ps[i].b<=ps[j].b){
                adde(i+1,n+j+1,1,ps[i].a*ps[i].b);
            }
            adde(S,i+1,1,0);
            adde(n+i+1,T,1,0);
            adde(i+1,T,1,0);
        }
        while(sp())mcs();
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Selct 大全
    Web API
    其他
    ADO.NET Entity Framework
    ORACLE SQL前端补0的三种方式。
    linux常用命令
    oracle 创建修改 job
    oracle 如何恢复误删的表记录数据
    myeclipse上SVN代码合并详细步骤图解
    SVN创建资源与分支详解
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5858183.html
Copyright © 2020-2023  润新知