POJ3422 Kaka's Matrix Travels 【费用流】*
POJ3422 Kaka’s Matrix Travels
Description
On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels with SUM = 0. For each travel, Kaka moves one rook from the left-upper grid to the right-bottom one, taking care that the rook moves only to the right or down. Kaka adds the number to SUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximum SUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximum SUM he can obtain after his Kth travel. Note the SUM is accumulative during the K travels.
Input
The first line contains two integers N and K (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The following N lines represents the matrix. You can assume the numbers in the matrix are no more than 1000.
Output
The maximum SUM Kaka can obtain after his Kth travel.
Sample Input
3 2
1 2 3
0 2 1
1 4 2
Sample Output
15
题意大概就是给你一个n*n的矩形,每一个方格中有一个权值,定义一次行走是从左上角走到右下角,而且每一次移动只能向右边或者下边移动,现在我们要行走k次,并使经过的点集的和最大(每个点值计算一次)
我们很容易想到把每个点的权值作为这个点某种意义上的费用(因为只能计算一次,后面会介绍建图方法),然后我们想最大化这个费用,所以对于这种问题我们可以见图的时候将边权取相反数,然后再跑出最小费用大流的时候将费用取相反数,不难发现这个时候的费用是最大化的
然后我们怎么处理一个节点的边权只能计算一次这个条件呢?
不妨这样思考,我们把一个点i拆成两个点i" role="presentation">ii和i+n∗n" role="presentation">i+n∗ni+n∗n,在i" role="presentation">ii和i+n∗n" role="presentation">i+n∗ni+n∗n之间连接两条弧:
1:一条容量为1,费用为负边权
2:一条容量为k-1,费用为0
我们可以很容易得到如果有流量经过弧2,一定有流量经过弧1,不然就不满足最小费用的性质
又对于两个节点i" role="presentation">ii和j" role="presentation">jj,满足j在i的下边或右边,即i" role="presentation">ii可以到达j" role="presentation">jj,那么我们可以把i+n∗n" role="presentation">i+n∗ni+n∗n连接到j" role="presentation">jj,这样流经i" role="presentation">ii的流量就可以流到j" role="presentation">jj了
现在我们只需要保证源点S流到第一个节点(坐标(1,1))的容量是k就好了
整理一下构图思路:
1 从S" role="presentation">SS连接到第一个节点(1,1)" role="presentation">(1,1)(1,1),容量为k
2 从i" role="presentation">ii到i+n∗n" role="presentation">i+n∗ni+n∗n连接两条弧:
" role="presentation"> 1:一条容量为1,费用为负边权
" role="presentation"> 2:一条容量为k-1,费用为0
3 对于i" role="presentation">ii到可以到达的j" role="presentation">jj连接一条从i+n∗n" role="presentation">i+n∗ni+n∗n到j" role="presentation">jj的边
4 从最后一个节点(n,n)" role="presentation">(n,n)(n,n)连接到汇点T" role="presentation">TT
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
#define N 100010
#define INF 0x3f3f3f3f
struct Edge{
int u,v,cap,flow,cost;
Edge(int xu,int xv,int xcap,int xflow,int xcost){
u=xu;v=xv;cap=xcap;flow=xflow;cost=xcost;
}
};
struct MCMF{
int s,t,f[N],p[N],d[N];
bool inq[N];
vector<Edge> E;
vector<int> G[N];
void add(int u,int v,int cap,int cost){
E.push_back(Edge(u,v,cap,0,cost));
E.push_back(Edge(v,u,0,0,-cost));
int m=E.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
}
bool SPFA(int &flow,int &cost){
memset(inq,0,sizeof(inq));
memset(d,0x3f,sizeof(d));
queue<int> Q;Q.push(s);
d[s]=0;f[s]=INF;
while(!Q.empty()){
int u=Q.front();Q.pop();
inq[u]=0;
for(int i=0;i<G[u].size();i++){
Edge e=E[G[u][i]];
if(d[e.v]>d[u]+e.cost&&e.cap>e.flow){
d[e.v]=d[u]+e.cost;
p[e.v]=G[u][i];
f[e.v]=min(f[u],e.cap-e.flow);
if(!inq[e.v]){
Q.push(e.v);
inq[e.v]=1;
}
}
}
}
if(d[t]==INF)return false;
flow+=f[t];cost+=f[t]*d[t];
int u=t;
while(u!=s){
E[p[u]].flow+=f[t];
E[p[u]^1].flow-=f[t];
u=E[p[u]].u;
}
return true;
}
int Min_cost_Max_flow(){
int flow=0,cost=0;
while(SPFA(flow,cost));
return cost;
}
}mcmf;
int n,k;
int g[100][100];
int Index(int x,int y){return (x-1)*n+y;}
int main(){
scanf("%d%d",&n,&k);
mcmf.s=0;mcmf.t=2*n*n+1;
mcmf.add(0,1,k,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&g[i][j]);
int tmp=Index(i,j);
mcmf.add(tmp,tmp+n*n,1,-g[i][j]);
mcmf.add(tmp,tmp+n*n,k-1,0);
if(i<n){
int tmp1=Index(i+1,j);
mcmf.add(tmp+n*n,tmp1,INF,0);
}
if(j<n){
int tmp1=Index(i,j+1);
mcmf.add(tmp+n*n,tmp1,INF,0);
}
}
}
mcmf.add(2*n*n,2*n*n+1,k,0);
printf("%d",-mcmf.Min_cost_Max_flow());
return 0;
}
POJ3422 Kaka's Matrix Travels 【费用流】*的更多相关文章
- POJ3422 Kaka's Matrix Travels[费用流]
Kaka's Matrix Travels Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9522 Accepted: ...
- poj 3422 Kaka's Matrix Travels 费用流
题目链接 给一个n*n的矩阵, 从左上角出发, 走到右下角, 然后在返回左上角,这样算两次. 一共重复k次, 每个格子有值, 问能够取得的最大值是多少, 一个格子的值只能取一次, 取完后变为0. 费用 ...
- poj3422 Kaka's Matrix Travels(最小费用最大流问题)
/* poj3422 Kaka's Matrix Travels 不知道 k次 dp做为什么不对??? 看了大牛的代码,才知道还可以这样做! 开始没有理解将a 和 a‘ 之间建立怎样的两条边,导致程序 ...
- POJ3422 Kaka's Matrix Travels
描述 On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels wi ...
- POJ 3422 Kaka's Matrix Travels(费用流)
Kaka's Matrix Travels Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6792 Accepted: ...
- POJ 3422 Kaka's Matrix Travels
Kaka's Matrix Travels Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9567 Accepted: ...
- POJ 3422 Kaka's Matrix Travels (K取方格数:最大费用流)
题意 给出一个n*n大小的矩阵,要求从左上角走到右下角,每次只能向下走或者向右走并取数,某位置取过数之后就只为数值0,现在求解从左上角到右下角走K次的最大值. 思路 经典的费用流模型:K取方格数. 构 ...
- [poj] 3422 Kaka's Matrix Travels || 最小费用最大流
原题 给一个N*N的方阵,从[1,1]到[n,n]走K次,走过每个方格加上上面的数,然后这个格上面的数变为0.求可取得的最大的值. 要求最大值,所以把边权全为负跑最小费用即可.因为只有第一次经过该点的 ...
- POJ3422或洛谷2045 Kaka's Matrix Travels
POJ原题链接 洛谷原题链接 很裸的费用流. 将每个点\(x\)拆成\(x_1,x_2\),并从\(x_1\)向\(x_2\)连一条容量为\(1\),费用为该点的权值的边,以及一条容量为\(+\inf ...
随机推荐
- PHP处理MySQL事务代码
php使用mysqli进行事务处理 <?php$db = new mysqli("localhost","root",""," ...
- Ubuntu下搭建Spark运行环境
安装Spark的方式 现在有两种安装方式: 安裝spark notebook:已經把spark, scala, hadoop等等包起來了,裝好就能用GUI介面操作,適合測試用. 傳統方式安裝:慢慢裝s ...
- Java新建线程的3种方法
Java新建线程的3种方法 =================== Java创建线程有3种方法:(1)继承Thread;(2)实现Runnable接口:(3)实现Callable接口; 由于Java只 ...
- LR----实现WebService测试
测试WebService时,需要导入WSDL:同SoapUI WSDL:http://ws.webxml.com.cn/webservices/DomesticAirline.asmx?wsdl 场景 ...
- wget下载指定目录下的文件
wget -r -np -k -P ~/tmp/ http://xxx.com/download -P 表示下载到哪个目录-r 表示递归下载-np 表示不下载旁站连接.-k 表示将下载的网页里 ...
- @Primary-在spring中常被忽视的注解
在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的.但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary ...
- struts.xml路径修改后的web配置
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_9" ...
- day22 CMDB 基础部分 (一)
参考博客: http://www.cnblogs.com/alex3714/articles/5420433.html
- 【问题解决记录】无法识别的标志“-sdlMode”,在“p2”中
本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cnblogs.com/dbylk/ 这是本人第一次使用MarkDown编辑器,试试看效果-w-,下面是正文: 一.报错原因 昨 ...
- hdu3488
题解: 首先把每一个点拆到两边 然后做KM求最大 吧没一条边相反即可 代码: #include<cstdio> #include<cmath> #include<algo ...