题目大意:有一个n*n的矩阵,每个格子有一个非负整数,规定一个人从(1,1)开始,只能往右或下走,走到(n,n)为止,并把沿途的数取走,取走后数变为0。这个人共取n次,求取得的数的最大总和。

解题思路:由于取多少次不确定,所以不能用dp。

我们发现,一个格子只能从左边或上面走来,且数只能取到一次,那么我们可以把此题转化为最大费用最大流问题。首先拆点,将一个点拆成x和y,然后从x到y连一条容量为1,流量为x(x为这格的数)的边,然后再连一条容量为inf,费用为0的边,这样即可保证一个点可以走多次,而数只能取一次。然后连接a和b时,从a的y向b的x连一条容量为inf,费用为0的边。最后跑最大费用最大流即可。

实现时对于(i,j),我们把这个点的x编号为$(i-1)*n+j$,y编号为$(i-1)*n+j+n^2$即可。

以下为EK算法代码。

C++ Code:

#include<cstdio>
#include<vector>
#include<queue>
#include<string.h>
using namespace std;
#define inf 0x3f3f3f3f
#define N 1000000
struct edge{
int from,to,cap,cost,nxt;
}e[N];
int n,k,dis[N],a[N],pree[N],head[N],cnt;
bool vis[N];
queue<int>q;
inline void addedge(int from,int to,int cap,int cost){
e[++cnt]=(edge){from,to,cap,cost,head[from]};
head[from]=cnt;
e[++cnt]=(edge){to,from,0,-cost,head[to]};
head[to]=cnt;
}
bool spfa(int s,int t,int& flow,int& cost){
memset(pree,0,sizeof(pree));
memset(a,0x3f,sizeof(a));
memset(dis,200,sizeof(dis));
memset(vis,0,sizeof(vis));
vis[s]=1;
dis[s]=0;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].nxt){
if(e[i].cap>0&&dis[e[i].to]<dis[u]+e[i].cost){
dis[e[i].to]=dis[u]+e[i].cost;
pree[e[i].to]=i;
if(a[u]>e[i].cap)a[e[i].to]=e[i].cap;else a[e[i].to]=a[u];
if(!vis[e[i].to]){
vis[e[i].to]=1;
q.push(e[i].to);
}
}
}
}
if(dis[t]<1)return false;
flow+=a[t];
cost+=a[t]*dis[t];
for(int i=t;i!=s;i=e[pree[i]].from){
e[pree[i]].cap-=a[t];
e[pree[i]^1].cap+=a[t];
}
return true;
}
int main(){
cnt=1;
scanf("%d%d",&n,&k);
int m=n*n;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
int x;
scanf("%d",&x);
addedge((i-1)*n+j,(i-1)*n+j+m,inf,0);
addedge((i-1)*n+j,(i-1)*n+j+m,1,x);
if(i>1){
addedge((i-2)*n+j+m,(i-1)*n+j,inf,0);
}
if(j>1){
addedge((i-1)*n+j-1+m,(i-1)*n+j,inf,0);
}
if(i==1&&j==1){
addedge(0,1,inf,0);
}
}
}
int flow=0,cost=0;
while(k--)
if(!spfa(0,m<<1,flow,cost))break;
printf("%d\n",cost);
return 0;
}

[洛谷P2045]方格取数加强版的更多相关文章

  1. 洛谷 P2045 方格取数加强版【费用流】

        题目链接:https://www.luogu.org/problemnew/show/P2045 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现 ...

  2. 洛谷 - P2045 - 方格取数加强版 - 费用流

    原来这种题的解法是费用流. 从一个方格的左上走到右下,最多走k次,每个数最多拿走一次. 每次走动的流量设为1,起始点拆点成限制流量k. 每个点拆成两条路,一条路限制流量1,费用为价值相反数.另一条路无 ...

  3. 洛谷P2045 方格取数加强版(费用流)

    题意 题目链接 Sol 这题能想到费用流就不难做了 从S向(1, 1)连费用为0,流量为K的边 从(n, n)向T连费用为0,流量为K的边 对于每个点我们可以拆点限流,同时为了保证每个点只被经过一次, ...

  4. 洛谷P2045 方格取数加强版 最小费用流

    Code: #include<cstdio> #include<cstring> #include<algorithm> #include<queue> ...

  5. P2045 方格取数加强版

    P2045 方格取数加强版 题目描述 给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格 ...

  6. 棋盘DP三连——洛谷 P1004 方格取数 &&洛谷 P1006 传纸条 &&Codevs 2853 方格游戏

    P1004 方格取数 题目描述 设有N $\times N$N×N的方格图(N $\le 9$)(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字00.如下图所示(见样例): A ...

  7. 洛谷 P2774 方格取数问题 解题报告

    P2774 方格取数问题 题目背景 none! 题目描述 在一个有 \(m*n\) 个方格的棋盘中,每个方格中有一个正整数.现要从方格中取数,使任意 2 个数所在方格没有公共边,且取出的数的总和最大. ...

  8. 洛谷 P1004 方格取数 题解

    P1004 方格取数 题目描述 设有 \(N \times N\) 的方格图 \((N \le 9)\),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字\(0\).如下图所示(见样例): ...

  9. 洛谷 P1004 方格取数 【多进程dp】

    题目链接:https://www.luogu.org/problemnew/show/P1004 题目描述 设有N*N的方格图(N<=9),我们将其中的某些方格中填入正整数,而其他的方格中则放 ...

随机推荐

  1. MYSQL 5.7 MHA(GTID+ROW)部署及failover,online_change实战演练

    文章结构如下: 1.MHA简介 Masterhigh availability manager and toolsfor mysql,是日本的一位mysql专家采用perl语言编写的一个脚本管理工具, ...

  2. POJ 1944 并查集(模拟)

    思路: 肯定是要枚举断点的..就看枚举完断点以后怎么处理了-- 1.用类似并查集的思想- f[x]=max(f[x],y)表示x和y相连(一定要注意取max,,,血的教训) 复杂度O(np) 2.猥琐 ...

  3. (转)js document.all的用法

    document.all用法 一. document.all是页面内所有元素的一个集合.例如:      document.all(0)表示页面内第一个元素 二.document.all可以判断浏览器 ...

  4. 【原创】Spring连接、事务代码分析

    1.JdbcTemplate     当不使用事务时,jdbcTemplate的模板类,通过     Connection con = DataSourceUtils.getConnection(ge ...

  5. jquery获取焦点和失去焦点

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/ ...

  6. C#生成高清缩略图 (装在自OPEN经验库)

    来源 http://www.open-open.com/lib/view/open1389943861320.html 代码如下实现图片的高清缩略图 /// <summary> /// 为 ...

  7. centos下nginx配置

    转自  http://www.linuxidc.com/Linux/2016-09/134907.htm 安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Wi ...

  8. pic16F1938

    1.中断自动保存寄存器:W.STATUS.BSR.FSR和PCLATH,而且如果中断中需要改变这些寄存器,在Bank31中修改这些寄存器的影子寄存器即可. 2.RAM有1024字节,分为N个bank, ...

  9. 中级前端工程师要掌握的JavaScript 技巧

    1.判断对象的数据类型 2.Es5实现数组map方法 3.使用reduce实现数组map方法 4.ES5 实现数组filter方法 5.使用reduce实现filter方法 6.ES5 实现数组som ...

  10. TP框架传值

    /*TP框架传值*/ location.href = "../add/add/department/"+department+"/username/"+user ...