题意

给出一个n*n大小的矩阵,要求从左上角走到右下角,每次只能向下走或者向右走并取数,某位置取过数之后就只为数值0,现在求解从左上角到右下角走K次的最大值.

思路

经典的费用流模型:K取方格数。

构图方法:将矩阵的每个元素m[i][j]拆成两个点u=(i-1)*n+j和v=n*n+(i-1)*n+j,从u到v连两条边:
1> 连边(u,v),容量为1,费用值为m[i][j],这样可以保证每一个位置的数只被取一次
2> 连边(u,v),容量为INF,费用值为0,这样可以保证某位置取数被置为0之后,随便怎么取对最后的费用值不会产生影响
由于每次只能向下走或者向右走,所以需要连两条边:
1> 向下走:即从(i,j)到(i+1,j),连边v=n*n+(i-1)*n+j到i*n+j,容量为INF,费用为0
2> 向右走:即从(i,j)到(i,j+1),连边v=n*n+(i-1)*n+j到(i-1)*n+j+1,容量为INF,费用为0.
然后为了限制只走K次,需要添加源点s=0和汇点t=2*n*n+1,连边:s……矩阵左上角顶点1,容量为k,费用为0,连边矩阵右下角顶点被拆之后对应的顶点2*n*n……t,容量为K,费用为0,然后对所建立的图求解最大费用流即可.

代码

[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; i ++)
using namespace std;

const int MAXV = 200005;
const int MAXE = 100005;
const int oo = 0x3fffffff;

template <class NodesType>
struct Nodes{
NodesType dist;
int pre, head; //pre存前趋边, head存前向星
bool visit;
};
template <class EdgesType>
struct Edges{
int u, v, next;
EdgesType cost, flow;
};
template <class T>
struct MinCostMaxFlow{
Nodes <T> node[MAXV];
Edges <T> arc[2*MAXE];
int vn, en;
void init(int n){
vn = n;
en = 0;
for (int i = 0; i <= n; i ++){
node[i].head = -1;
}
}
void insert_flow(int u, int v, T flow, T cost){
arc[en].u = u;
arc[en].v = v;
arc[en].flow = flow;
arc[en].cost = cost;
arc[en].next = node[u].head;
node[u].head = en ++;
arc[en].v = u;
arc[en].u = v;
arc[en].flow = 0;
arc[en].cost = -cost;
arc[en].next = node[v].head;
node[v].head = en ++;
}
void print_edges(){
for (int i = 0; i < en; i ++){
printf("u = %d v = %d flow = %d cost = %d\n", arc[i].u, arc[i].v, arc[i].flow, arc[i].cost);
}
}
queue <int> q;
bool spfa(int s, int t){
for (int i = 1; i <= vn; i ++){
node[i].dist = oo;
node[i].pre = -1;
node[i].visit = false;
}
node[s].dist = 0;
node[s].visit = true;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
node[u].visit = false;
for (int i = node[u].head; i != -1; i = arc[i].next){
int v = arc[i].v;
if (arc[i].flow > 0 && node[v].dist > node[u].dist + arc[i].cost){
node[v].dist = node[u].dist + arc[i].cost;
node[v].pre = i;
if (!node[v].visit){
node[v].visit = true;
q.push(v);
}
}
}
}
if (node[t].pre == -1)
return 0;
else
return 1;
}
T solve(int s, int t, T &mincost){
mincost = 0;
T maxflow = 0;
while(spfa(s, t)){
T minflow = oo;
for (int i = node[t].pre; i != -1; i = node[arc[i].u].pre){
minflow = min(minflow, arc[i].flow);
}
for (int i = node[t].pre; i != -1; i = node[arc[i].u].pre){
arc[i].flow -= minflow;
arc[i^1].flow += minflow;
mincost += arc[i].cost * minflow;
}
maxflow += minflow;
}
return maxflow;
}
};
MinCostMaxFlow <int> mcmf;

int map[55][55];
int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n, k;
while(scanf("%d %d", &n, &k) != EOF){
mcmf.init(2*n*n+2);
mcmf.insert_flow(2*n*n+1, 1, k, 0);
mcmf.insert_flow(2*n*n, 2*n*n+2, k, 0);
REP(i, 1, n)
REP(j, 1, n){
scanf("%d", &map[i][j]);
int u = (i-1)*n+j;
mcmf.insert_flow(u, u+n*n, 1, -map[i][j]);
mcmf.insert_flow(u, u+n*n, oo, 0);
if (i < n){
mcmf.insert_flow(u+n*n, u+n, oo, 0);
}
if (j < n){
mcmf.insert_flow(u+n*n, u+1, oo, 0);
}
}
//mcmf.print_edges();
int res = 0;
mcmf.solve(2*n*n+1, 2*n*n+2, res);
printf("%d\n", -res);
}
return 0;
}
[/cpp]

POJ 3422 Kaka's Matrix Travels (K取方格数:最大费用流)的更多相关文章

  1. POJ 3422 Kaka's Matrix Travels K取方格数

    题目:给出n*n的方格矩阵,现在从左上方走m次到右下方,问m次能够获得的最大价值和. 分析:最大费用流.拆点进行限制每个格子只取一次,假设点x拆成 x,xx,右边(假设有)y,yy,下方(假设有)z, ...

  2. Luogu2045 方格取数加强版(K取方格数) 费用流

    题目传送门 题意:给出一个$N \times N$的方格,每个格子中有一个数字.你可以取$K$次数,每次取数从左上角的方格开始,每一次只能向右或向下走一格,走到右下角结束,沿路的方格中的数字将会被取出 ...

  3. POJ 3422 Kaka's Matrix Travels

    Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9567   Accepted:  ...

  4. POJ 3422 Kaka's Matrix Travels(费用流)

    Kaka's Matrix Travels Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6792   Accepted:  ...

  5. poj 3422 Kaka's Matrix Travels 费用流

    题目链接 给一个n*n的矩阵, 从左上角出发, 走到右下角, 然后在返回左上角,这样算两次. 一共重复k次, 每个格子有值, 问能够取得的最大值是多少, 一个格子的值只能取一次, 取完后变为0. 费用 ...

  6. [poj] 3422 Kaka's Matrix Travels || 最小费用最大流

    原题 给一个N*N的方阵,从[1,1]到[n,n]走K次,走过每个方格加上上面的数,然后这个格上面的数变为0.求可取得的最大的值. 要求最大值,所以把边权全为负跑最小费用即可.因为只有第一次经过该点的 ...

  7. POJ 3422 Kaka's Matrix Travels(最小费用最大流)

    http://poj.org/problem?id=3422 题意 : 给你一个N*N的方格,每个格子有一个数字,让你从左上角开始走,只能往下往右走,走过的数字变为0,走K次,问最大能是多大,累加的. ...

  8. POJ 3422 Kaka's Matrix Travels 【最小费用最大流】

    题意: 卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下.矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和. 思路: 最小费用最大流的题 ...

  9. POJ 3422 Kaka's Matrix Travels(拆点+最大费用流)题解

    题意:小A从左上角走到右下角,每个格子都有一个价值,经过这个格子就把价值拿走,每次只能往下或往右走,问你走k次最多能拿多少价值的东西. 思路:这里有一个限制条件就是经过之后要把东西拿走,也就是每一格的 ...

随机推荐

  1. linux 下各个工具使用(screen、tmux,pyenv、virtualenv,pip国内源,tree)

    一.多会话工具screen.tmux 两个都是多窗口工具.1.使用后wim出现配色问题:http://ibartman.com/2014/04/16/vim%20%E9%85%8D%E8%89%B2/ ...

  2. POJ 2013

    #include <iostream> #include <string> #define MAXN 20 using namespace std; string _m[MAX ...

  3. Shell脚本基础II

    1.shell算术运算 1)加法 r=`expr 4 + 5`(注意! '4' '+' '5' 这三者之间要有空白) r=$[ 4 + 5 ] r=$(( 4 + 5 )) echo $r 2)乘法 ...

  4. iOS 开发--动画

    在iOS开发中,制作动画效果是最让开发者享受的环节之一.一个设计严谨.精细的动画效果能给用户耳目一新的效果,吸引他们的眼光 —— 这对于app而言是非常重要的.我们总是追求更为酷炫的实现,如果足够仔细 ...

  5. PHP页面跳转几种实现技巧

    PHP被许多程序员用来开发WEB的首选语言.在实际开发中,网站的各项功能都可以通过PHP语言的编写来满足,比如PHP页面跳转这一方法. 探讨PHP变量解析顺序如何获取提交数据 深入解读PHP运行机制 ...

  6. vmware通过vmnet8共享本地网络

    转载于:http://zhaolongchn.blog.163.com/blog/static/19065850420122595117886/ 1,首先将真实电脑的虚拟网卡VMnet8启用 2,然后 ...

  7. 根据ip查询地区,经纬度等-geoip2

    这项工作难度主要在数据上,数据越准确越有利. 1. 下载数据文件: http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.m ...

  8. Bridging signals---hdu1950(最长上升子序列复杂度n*log(n) )

     题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1950 一直只知道有除n*n的算法之外的求LIS,但是没学过,也没见过,今天终于学了一下,dp[i]表 ...

  9. 关于LINUX权限-bash: ./startup.sh: Permission denied

    关于LINUX权限-bash: ./startup.sh: Permission denied <script type="text/javascript"></ ...

  10. 使用grep查找文件中指定字符出现的次数

    grep -o ‘好' 文件名.txt | wc -l -o 指示grep显示所有匹配的地方,并且每一个匹配单独一行输出.这样只要统计输出的行数就可以知道这个字符出现的次数了.