zoukankan      html  css  js  c++  java
  • 方格取数 2

    方格取数 2

     时间限制: 1 s
     空间限制: 128000 KB
     
     
     
    题目描述 Description

    给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

    输入描述 Input Description

    第一行两个数n,k(1<=n<=50, 0<=k<=10)

    接下来n行,每行n个数,分别表示矩阵的每个格子的数

    输出描述 Output Description

    一个数,为最大和

    样例输入 Sample Input

    3 1

    1 2 3

    0 2 1

    1 4 2

    样例输出 Sample Output

    11

    数据范围及提示 Data Size & Hint

    1<=n<=50, 0<=k<=10


    网络流。考虑将每个方格拆成两个点x,y。每个方格的x,y点之间连一条容量为1,费用为权值的边,每个方格的x,y点都分别和右边,下边格子的x点连一条容量为k,费用为0的边。
    这样连边的原因:每个方格的x,y点连边代表如果选这个格子里的数,就有流量通过这个边,但是考虑到一个格子可能被走多次,所以除了y点要和其他格子连边,x点也要和其他格子连边,代表不选这个格子里的数。
    最后跑最大费用最大流。
    #include<bits/stdc++.h>
    #define N 5200
    #define INF LLONG_MAX/4
    using namespace std;
    struct MCMF
    {
        struct Edge
        {
            long long  from,to,flow,cost;
        };
    
        vector<Edge> edges;
        vector<long long > G[N];
        long long  inq[N];//是否在队列中
        long long  d[N];//距离
        long long  p[N];//上一条弧
        long long  a[N];//可改进量
    
        void init()//初始化
        {
            for(long long  i=0; i<N; i++)G[i].clear();
            edges.clear();
        }
    
        void addedge(long long  from,long long  to,long long  flow,long long  cost)//加边
        {
            edges.push_back((Edge){from,to,flow,cost});
            edges.push_back((Edge){to,from,0,-cost});
            long long  m=edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
    
        bool SPFA(long long  s,long long  t,long long  &flow,long long  &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost
        {
            
            for(long long  i=0; i<N; i++)d[i]=INF,inq[i]=0;
            d[s]=0;
            inq[s]=1;
            p[s]=0;
            a[s]=INF;
            queue<long long > Q;
            Q.push(s);
            while(!Q.empty())
            {
                long long  u=Q.front();
                Q.pop();
                inq[u]=0;
                for(long long  i=0; i<G[u].size(); i++)
                {
                    Edge& e=edges[G[u][i]];
                    if(e.flow>0 && d[e.to]>d[u]+e.cost)//满足可增广且可变短
                    {
                    //    printf("%d %d
    ",e.from,e.to);
                        
                        d[e.to]=d[u]+e.cost;
                        p[e.to]=G[u][i];
                        a[e.to]=min(a[u],e.flow);
                        if(!inq[e.to])
                        {
                            inq[e.to]=1;
                            Q.push(e.to);
                        }
                    }
                }
            }
            if(d[t]==INF) return false;//汇点不可达则退出
            flow+=a[t];
            cost+=d[t]*a[t];
            long long  u=t;
            while(u!=s)//更新正向边和反向边
            {
                edges[p[u]].flow-=a[t];
                edges[p[u]^1].flow+=a[t];
                u=edges[p[u]].from;
            }
            return true;
        }
    
    
        void MincotMaxflow(long long  s,long long  t,long long  &flow,long long  &cost)
        {
            while(SPFA(s,t,flow,cost));//{cost=0;flow=long long _MAX;}
        }
    };
    
    MCMF mcmf;
    int main()
    {
        int n,k;
        int a[55][55];
        int x[55][55],y[55][55];
        scanf("%d %d",&n,&k);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
    
        int cut=1;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            x[i][j]=2*cut-1;
            y[i][j]=2*cut;
            cut++;
        }
    
        mcmf.init();
    
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                mcmf.addedge(x[i][j],y[i][j],1,-a[i][j]);
            }
            
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(i+1<=n)
            {
                mcmf.addedge(x[i][j],x[i+1][j],k,0);
                mcmf.addedge(y[i][j],x[i+1][j],k,0);
            }
    
            if(j+1<=n)
            {
                mcmf.addedge(x[i][j],x[i][j+1],k,0);
                mcmf.addedge(y[i][j],x[i][j+1],k,0);
            }
        }
    
        int s=n*n*2+1,t=n*n*2+2;
        mcmf.addedge(s,x[1][1],k,0);
        mcmf.addedge(x[n][n],t,k,0);
        mcmf.addedge(y[n][n],t,k,0);
    
    
        long long flow=0,cost=0;
        mcmf.MincotMaxflow(s,t,flow,cost);
        printf("%lld",-cost);
        return 0;
    
    }
    View Code
     
  • 相关阅读:
    一行代码更改博客园皮肤
    fatal: refusing to merge unrelated histories
    使用 netcat 传输大文件
    linux 命令后台运行
    .net core 使用 Nlog 配置文件
    .net core 使用 Nlog 集成 exceptionless 配置文件
    Mysql不同字符串格式的连表查询
    Mongodb between 时间范围
    VS Code 使用 Debugger for Chrome 调试vue
    css权重说明
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9458192.html
Copyright © 2011-2022 走看看