POJ 3422 Kaka's Matrix Travels (K取方格数:最大费用流)
题意
给出一个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取方格数:最大费用流)的更多相关文章
- POJ 3422 Kaka's Matrix Travels K取方格数
题目:给出n*n的方格矩阵,现在从左上方走m次到右下方,问m次能够获得的最大价值和. 分析:最大费用流.拆点进行限制每个格子只取一次,假设点x拆成 x,xx,右边(假设有)y,yy,下方(假设有)z, ...
- Luogu2045 方格取数加强版(K取方格数) 费用流
题目传送门 题意:给出一个$N \times N$的方格,每个格子中有一个数字.你可以取$K$次数,每次取数从左上角的方格开始,每一次只能向右或向下走一格,走到右下角结束,沿路的方格中的数字将会被取出 ...
- 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(费用流)
Kaka's Matrix Travels Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6792 Accepted: ...
- poj 3422 Kaka's Matrix Travels 费用流
题目链接 给一个n*n的矩阵, 从左上角出发, 走到右下角, 然后在返回左上角,这样算两次. 一共重复k次, 每个格子有值, 问能够取得的最大值是多少, 一个格子的值只能取一次, 取完后变为0. 费用 ...
- [poj] 3422 Kaka's Matrix Travels || 最小费用最大流
原题 给一个N*N的方阵,从[1,1]到[n,n]走K次,走过每个方格加上上面的数,然后这个格上面的数变为0.求可取得的最大的值. 要求最大值,所以把边权全为负跑最小费用即可.因为只有第一次经过该点的 ...
- POJ 3422 Kaka's Matrix Travels(最小费用最大流)
http://poj.org/problem?id=3422 题意 : 给你一个N*N的方格,每个格子有一个数字,让你从左上角开始走,只能往下往右走,走过的数字变为0,走K次,问最大能是多大,累加的. ...
- POJ 3422 Kaka's Matrix Travels 【最小费用最大流】
题意: 卡卡有一个矩阵,从左上角走到右下角,卡卡每次只能向右或者向下.矩阵里边都是不超过1000的正整数,卡卡走过的元素会变成0,问卡卡可以走k次,问卡卡最多能积累多少和. 思路: 最小费用最大流的题 ...
- POJ 3422 Kaka's Matrix Travels(拆点+最大费用流)题解
题意:小A从左上角走到右下角,每个格子都有一个价值,经过这个格子就把价值拿走,每次只能往下或往右走,问你走k次最多能拿多少价值的东西. 思路:这里有一个限制条件就是经过之后要把东西拿走,也就是每一格的 ...
随机推荐
- (转)单机上配置hadoop
哈哈,几天连续收到百度两次电话,均是利好消息,于是乎不知不觉的自己的工作效率也提高了,几天折腾了好久终于在单机上配置好了hadoop,然后也成功的运行了一个用例,耶耶耶耶耶耶. 转自:http://w ...
- JS之事件(一)
事件:交互 异步监听,不是JS引擎监听的 一.绑定 1.ele.onxxxx(eg:onclick) = function (e) { //回调函数/事件处理函数 } 兼容性很好,但同一个事件仅能绑定 ...
- 华为OJ:火车进站
火车进站 给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号.要求以字典序排序输出火车出站的序列号. 输入描述: 有多组测试用例, ...
- lintcode:颜色分类
颜色分类 给定一个包含红,白,蓝且长度为 n 的数组,将数组元素进行分类使相同颜色的元素相邻,并按照红.白.蓝的顺序进行排序. 我们可以使用整数 0,1 和 2 分别代表红,白,蓝. 样例 给你数组 ...
- JavaWeb项目开发案例精粹-第6章报价管理系统-001需求分析及设计
1. 2. 3. 4. 5. 6.
- Java-数据结构与算法-二分查找法
1.二分查找法思路:不断缩小范围,直到low <= high 2.代码: package Test; import java.util.Arrays; public class BinarySe ...
- JLink v8克隆版破解向导(此方法仅适用XP32位版 WIN7及以上和64位均不支持 建议使用虚拟机)
此方法仅适用XP32位版 WIN7及以上和64位均不支持 建议使用虚拟机 摘要 Jlink 4.5版本之后驱动会识别老的克隆版的JlinkV8,Jlink软件在启动时会提示为克隆版本后退出.目前主流的 ...
- 关于LINUX权限-bash: ./startup.sh: Permission denied
关于LINUX权限-bash: ./startup.sh: Permission denied <script type="text/javascript"></ ...
- iOS:CALayer的隐式动画的详解
CALayer的隐式动画属性: •每一个UIView内部都默认关联着一个CALayer,称这个Layer为Root Layer.所有的非Root Layer都存在着隐式动画,隐式动画的默认时长为1/4 ...
- stanford-postagger中文词性标注
安装 系统需要安装Java1.6+ http://nlp.stanford.edu/software/tagger.shtml 下载Download full Stanford Tagger vers ...