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

Kaka‘s Matrix Travels

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9460   Accepted: 3844

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

Source

【分析】下面是模板。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define inf 0x7fffffff
#define mod 10000
#define met(a,b) memset(a,b,sizeof a)
typedef long long ll;
using namespace std;
const int N = 100;
const int M = 100000;
struct Edge {
    int to,next,cap,flow,cost;
} edge[M];
int head[N],tol;
int pre[N],dis[N];
bool vis[N];
int T;//节点总个数,节点编号从0~N-1
void init(int n) {
    T = n;
    tol = 0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,int cost) {
    edge[tol].to = v;
    edge[tol].cap = cap;
    edge[tol].cost = cost;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].cost = -cost;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
bool spfa(int s,int t) {
    queue<int>q;
    for(int i = 0; i < N; i++) {
        dis[i] = inf;
        vis[i] = false;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while(!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            if(edge[i].cap > edge[i].flow &&
                    dis[v] > dis[u] + edge[i].cost ) {
                dis[v] = dis[u] + edge[i].cost;
                pre[v] = i;
                if(!vis[v]) {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(pre[t] == -1)return false;
    else return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s,int t,int &cost) {
    int flow = 0;
    cost = 0;
    while(spfa(s,t)) {
        int Min = inf;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
            if(Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
            edge[i].flow += Min;
            edge[i^1].flow -= Min;
            cost += edge[i].cost * Min;
        }
        flow += Min;
    }
    return flow;
}

int a[N][N];
int main() {
    int n,k;
    while(~scanf("%d%d",&n,&k) ) {
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                scanf("%d",&a[i][j]);
        init(2*n*n+2);
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++) {
                addedge(n*i+j+1,n*n+n*i+j+1,1,-a[i][j]);
                addedge(n*i+j+1,n*n+n*i+j+1,inf,0);
            }

        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++) {
                if(i < n-1)
                    addedge(n*n+n*i+j+1,n*(i+1)+j+1,inf,0);
                if(j < n-1)
                    addedge(n*n+n*i+j+1,n*i+j+1+1,inf,0);
            }
        addedge(0,1,k,0);
        addedge(2*n*n,2*n*n+1,inf,0);
        int cost;
        minCostMaxflow(0,2*n*n+1,cost);
        printf("%d\n",-cost);
    }
    return 0;
}

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

时间: 2024-12-20 04:20:20

POJ 3422Kaka's Matrix Travels(最小费用最大流)的相关文章

POj3422 Kaka&#39;s Matrix Travels 最小费用最大流 拆点

题目链接: poj3422 题意: 有一个N X N的矩阵, 矩阵的每一小格都有且仅有一个数字v,kaka每经过一个数字就会把它捡起来并将那个数字加到sum上去. 现在kaka能通过向下或向右走的方式从 (1,1)到(n,n)  K次,问kaka能取到的最大的sum是多少. 解题思路: 题目问题可以抽象为   求多次可走重复路的最长路的最大和问题 首先想到的就应该是最小费用最大流, 而题目要求的最大和值,那么应求就是最大费用最大流, 仅仅只需要将代码中的最小路算法改为最长路算法即可 题目的条件是

poj3422 Kaka&#39;s Matrix Travels(最小费用最大流问题)

1 /* 2 poj3422 Kaka's Matrix Travels 3 不知道 k次 dp做为什么不对??? 4 看了大牛的代码,才知道还可以这样做! 5 开始没有理解将a 和 a‘ 之间建立怎样的两条边,导致程序一直陷入死循环,真心花了好长时间,快崩溃了.无语..... 6 题意:有个方阵,每个格子里都有一个非负数,从左上角走到右下角,每次走一步,只能往右或往下走,经过的数字拿走 7 每次都找可以拿到数字和最大的路径走,走k次,求最大和 8 9 这是 最大费用最大流 问题 每次spfa都

POJ3422 Kaka&#39;s Matrix Travels(最大费用最大流 + 拆点)

题目链接:http://poj.org/problem?id=3422 题意:有一个n*n的矩阵,格子中的元素是费用,KaKa从左上角开始出发要到达右下角,但是他只能向下走或者向右走,且走过的格子赋值为0,可以走K次,问K次后KaKa能获得的最大费用是多少? 思路:首先解释一下为什么要拆点?    因为要获得最大费用,所以假设当前步选择先下走,最终得到的结果可能不是最大值,但根据题意却把走过的格子赋为0了,这就影响了最终结果.所以进行拆点,把每个点拆成两个点,入度点和出度点,本点的入度点连接着本

POJ 3686.The Windy&#39;s 最小费用最大流

The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5477   Accepted: 2285 Description The Windy's is a world famous toy factory that owns M top-class workshop to make toys. This year the manager receives N orders for toys. The ma

poj 2135 Farm Tour (最小费用最大流模板)

网络流的费用: 在实际应用中,与网络流有关的问题,不仅涉及流量,而且还有费用的因素.网络的每一条边(v,w)除了给定容量cap(v,w)外,还定义了一个单位流量费用cost(v,w) 最小费用最大流问题 给定网络G,要求G的一个最大用流flow,使流的总费用最小. 求解MCMF问题的算法: 最小费用最大流最常用和基本的算法我们可以称它为最小费用路算法,其思想与求最大流的增广路算法类似,不断在残流网络中寻找从源s到汇t的最小费用路,即残流网络中从s到t的以费用为权的最短路,然后沿最小费用路增流,直

POJ 2516 Minimum Cost(最小费用最大流啊)

题目链接:http://poj.org/problem?id=2516 Description Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy has M supply places (mar

POJ 2516 Minimum Cost (最小费用最大流)

POJ 2516 Minimum Cost 链接:http://poj.org/problem?id=2516 题意:有M个仓库,N个商人,K种物品.先输入N,M,K.然后输入N行K个数,每一行代表一个商人要购买的物品,其中K个数分别表示要购买的每件商品数.然后是M行K个数,每行表示仓库里的情况,其中K个数分别每种物品的库存量.接下来是K个矩阵,每个矩阵为N*M,分别表示第K种物品从M个仓库运到第N个商人的花费.问能否合理安排,使得花费最少,如果不行就输出-1. 思路: 一开始的时候,竟然构造了

poj 2516 Minimum Cost 【最小费用最大流】

题目:poj 2516 Minimum Cost 题意:有 n 个商店,k种物品和 m 个供货商,让你求进满足商店需求的货物的最小花费? 有必要说一下输入数据. 首先n ,k ,m 然后是一个n*m的矩阵,n个商店对每种货物的需求,表示第 i 个商店需要第 j 种货物 x个 然后是m * k 的矩阵,m个供货商可以供k种货物的数量,表示第 i 个供货商 提供第 j 中货物 x 个 接下来是 k 个 n * m 的矩阵,表示第 i 个货物,由 k 供应商发货给 j 商店的价格x (注意如果供不应求

poj 2526 Minimum Cost【最小费用最大流】

题目链接:http://poj.org/problem?id=2516 题意: n个店主 m个供应商 k种货物 给你店主对k种货物的需求及供货商k种货物的囤货量及K种运输费用. 解法:k次费用流,分别求每种货物的费用.源点到供应点建边,店主到汇点建边,费用均为0,容量为1.然后供应点到店主建边,费用为矩阵,容量无穷大即可. 代码: /* POJ 2195 Going Home 邻接矩阵形式最小费用最大流 */ #include<stdio.h> #include<iostream>