zoukankan      html  css  js  c++  java
  • 球的移动(move)

    有n个盒子(1<=N<=1000)围成一个圈,每个盒子有ai个球,所有盒子的球的总数小于等于n.每一次移动,可以把一个球移动到它的一个相邻的盒子内.
    现在要使得每个盒子的球数<=1,求最少的移动次数

    输入格式:

    n
    a1
    a2

    an

    输出格式:

    最少移动次数

    样例输入:

    12
    0
    0
    2
    4
    3
    1
    0
    0
    0
    0
    0
    1
    

    样例输出:

    19

    网络流真乃xjb题的解题法宝

    费用流。
    先设超级源点0和超级汇点2*n+1,然后将每个点拆成源点和汇点,然后每个源点先与对应汇点连一条容量无限大,费用为0的边;然后与相邻点的汇点连容量无限大,费用为1的边,最后将各源点与超级源点连一条容量为a[i]费用为0的边,各汇点与超级汇点连一条容量为1费用为0的边,然后跑一遍费用流即可。(为什么?自己思考吧)
     
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    struct edge{
        int v,c,f;
    }e[100010];
    int fi[100010],ne[100010],la[100010],q[200020],d[100010],flow[100010],x,ansflow,anscost,tot,pe[100010],n,m,s,t,b[200010],pre[200010],u,v,w,f;
    void add(int x,int y,int f,int c){
        e[++tot].v=y;e[tot].c=c;e[tot].f=f;
        !fi[x]?fi[x]=tot:ne[la[x]]=tot;la[x]=tot;
        e[++tot].v=x;e[tot].c=-c;e[tot].f=0;
        !fi[y]?fi[y]=tot:ne[la[y]]=tot;la[y]=tot;
    }
    bool spfa(int s,int t){
        int H=0,T=0;
        memset(d,0x3f,sizeof(d));
        memset(flow,0,sizeof(flow));
        q[++T]=s;b[s]=1;d[s]=0;pre[s]=0;flow[s]=0x7fffffff;
        while(H<T){
            int x=q[++H];
            for(int i=fi[x];i;i=ne[i]){
                int y=e[i].v,z=e[i].f,c=e[i].c;    
                if(z>0&&d[y]>d[x]+c){
                    d[y]=d[x]+c;
                    pre[y]=x;
                    pe[y]=i;
                    flow[y]=min(flow[x],z);
                    if(!b[y])b[y]=1,q[++T]=y;
                }
            }
        
            b[x]=0;
        }
        return d[t]!=0x3f3f3f3f;
    }
    void maxflow(){
        while(spfa(s,t)){
            int k=t;
            while(k!=s){
                e[pe[k]].f-=flow[t];
                e[pe[k]^1].f+=flow[t];
                k=pre[k];
            }
            ansflow+=flow[t];
            anscost+=d[t]*flow[t];
        }
    }
    int main(){
        scanf("%d",&n);
        tot=1;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);    
            int pr=i==1?n:i-1,nx=i==n?1:i+1;
            add(0,i,x,0);
            add(i,nx+n,0x3f3f3f3f,1);
            add(nx+n,i,0x3f3f3f3f,1);
            add(i,pr+n,0x3f3f3f3f,1);
            add(pr+n,i,0x3f3f3f3f,1);
            add(i,i+n,0x3f3f3f3f,0);
            add(i+n,i,0x3f3f3f3f,0);
            add(i+n,2*n+1,1,0);
        }
        s=0;t=2*n+1;
        maxflow();
        printf("%d",anscost);
    }
    
    
     
     
     
  • 相关阅读:
    org.springframework.beans.factory.BeanCreationException
    线程浅谈
    第五次作业
    第四次作业
    第三次作业
    第二次作业
    第一次作业
    第五次作业
    第三次作业
    第二次作业
  • 原文地址:https://www.cnblogs.com/sffey/p/6934401.html
Copyright © 2011-2022 走看看