zoukankan      html  css  js  c++  java
  • P2045 方格取数加强版 最小费用最大流

      

    题目描述

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

    输入输出格式

    输入格式:

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

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

    输出格式:

    一个数,为最大和

    输入输出样例

    输入样例#1: 复制
    3 1
    1 2 3
    0 2 1
    1 4 2
    输出样例#1: 复制
    11

    说明

    每个格子中的数不超过1000

    这题是最大费用

    最大流是跑满k次 

    最大费用为取数的结果

    1. 点边转化:把每个格子 (i,j) 拆成一个入点一个出点。
    2. 从每个入点向对应的出点连两条有向边:一条容量为 11 ,费用为格子 (i,j) 中的数;另一条容量为 k-1 ,费用为 0 。(满足了 取一次能拿到c值   然后其他“取法” 也可以经过该点)
    3. 从 (i,j)(i,j) 的出点到 (i,j+1) 和 (i+1,j)的入点连有向边,容量为 k ,费用为 0 。
    4. 以 (1,1) 的入点为源点, (n,n) 的出点为汇点,求最大费用最大流。
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);--i)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define pb push_back
    #define inf 0x3f3f3f3f
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    const int N=100001;
    
    int n,m,S,T,k,maxflow,mincost,last[N],pre[N],dis[N],flow[N];
    bool vis[N];
    struct Edge{
        int next,to,flow,dis;
    }edge[N<<1];
    int pos=1,head[N];
    void init()
    {
        pos=1;
        CLR(head,0);
        mincost=maxflow=0;
    }
    queue <int> q;
    int id(int x,int y) {return n*(x-1)+y;}
    
    void add(int from,int to,int flow,int dis)//flow流量 dis费用
    {
        edge[++pos].next=head[from];
        edge[pos].flow=flow;
        edge[pos].dis=dis;
        edge[pos].to=to;
        head[from]=pos;
    
        edge[++pos].next=head[to];
        edge[pos].flow=0;
        edge[pos].dis=-dis;
        edge[pos].to=from;
        head[to]=pos;
    
    }
    bool spfa(int s,int t)
    {
        CLR(dis,0x3f);
        CLR(flow,0x3f);
        CLR(vis,0);
        while (!q.empty()) q.pop();
        dis[s]=0; pre[t]=-1; q.push(s); vis[s]=1;
        int tot=0;
        while (!q.empty())
        {
            int now=q.front(); q.pop(); vis[now]=0;
            for (int i=head[now]; i; i=edge[i].next)
            {
                int to=edge[i].to;
                if  (edge[i].flow>0 && dis[to]>dis[now]+edge[i].dis)
                {
                    dis[to]=edge[i].dis+dis[now];
                    flow[to]=min(edge[i].flow,flow[now]);
                    last[to]=i;
                    pre[to]=now;
                    if (!vis[to])
                    {
                        q.push(to); vis[to]=1;
                    }
                }
            }
        }
        return pre[t]!=-1;
    }
    void MCMF(int s,int t)
    {
        while (spfa(s,t))
        {
            int now=t;
            maxflow+=flow[t];
            mincost+=flow[t]*dis[t];
            while (now!=s)
            {
                edge[last[now]].flow-=flow[t];//dis . flow
                edge[last[now]^1].flow+=flow[t];
                now=pre[now];
            }
        }
    }
    int main()
    {   
        init();
        cin>>n>>k;
        int T=n*n+10;
        rep(i,1,n)
        rep(j,1,n)
        {
            int x;RI(x);x=-x;
            add(id(i,j),id(i,j)+T,1,x);
            add(id(i,j),id(i,j)+T,k-1,0);
            if(j<n)add(id(i,j)+T,id(i,j+1),k,0);
            if(i<n)add(id(i,j)+T,id(i+1,j),k,0);
        }
        int s=id(1,1);
        int t=id(n,n)+T;
    
        MCMF(s,t);
        cout<<-mincost;
        return 0;
    }
    View Code
  • 相关阅读:
    2.12 使用@DataProvider
    2.11 webdriver中使用 FileUtils ()
    Xcode8 添加PCH文件
    The app icon set "AppIcon" has an unassigned child告警
    Launch Image
    iOS App图标和启动画面尺寸
    iPhone屏幕尺寸、分辨率及适配
    Xcode下载失败 使用已购项目页面再试一次
    could not find developer disk image
    NSDate与 NSString 、long long类型的相互转化
  • 原文地址:https://www.cnblogs.com/bxd123/p/10940019.html
Copyright © 2011-2022 走看看