POJ3422 Kaka's Matrix Travels 【最大费用最大流】

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

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

POJ Monthly--2007.10.06, Huang, Jinsong

题意:有一个NxN的棋盘,小明从左上角开始走到右下角,只能向右和向下走,每个落子点都有一个非负整数,小明每次经过一个落子点都会将点的值加到sum上,同时该点的值清零,问:如果小明走K次的话sum的最大值是多少,同一个点可以走多次。

题解:拆点+费用流,走K次表示最大流为K,求sum最大值表示求最大费用,构图时要将点权拆分成边权,比如点X,拆成X到X'有一条容量为1的边,费用为该点原来的值,再在X到X'间加一条边,容量inf,费用0,然后再用X'跟其他点相连,由于是求最大费用,因此每次增广路时SPFA都要向大松弛。


#include <stdio.h>
#include <string.h>
#include <queue>
#define inf 0x3f3f3f3f
#define maxN 55
#define maxn maxN * maxN * 2
#define maxm maxn * 4
using std::queue;

int head[maxn], n, k, id;
struct Node {
    int u, v, c, f, next;
} E[maxm];
int dist[maxn], map[maxN][maxN];
int pre[maxn], source, sink;
bool vis[maxn];

void addEdge(int u, int v, int c, int f) {
    E[id].u = u; E[id].v = v; E[id].f = f;
    E[id].c = c; E[id].next = head[u];
    head[u] = id++;
    E[id].u = v; E[id].v = u; E[id].f = -f;
    E[id].c = 0; E[id].next = head[v];
    head[v] = id++;
}

void getMap() {
    memset(head, -1, sizeof(head));
    int i, j, f, pos, down, right; id = 0;
    for(i = 0; i < n; ++i)
        for(j = 0; j < n; ++j) {
            scanf("%d", &map[i][j]);
            pos = i * n + j; right = pos + 1;
            down = pos + n;
            addEdge(pos, pos + n*n, 1, map[i][j]); // 拆点
            addEdge(pos, pos + n*n, inf, 0);
            if(i != n - 1) {
                addEdge(pos + n*n, down, inf, 0);
            }
            if(j != n - 1) {
                addEdge(pos + n*n, right, inf, 0);
            }
        }
    source = 2 * n * n; sink = source + 1;
    map[n][0] = map[n][1] = 0;
    addEdge(source, 0, k, 0);
    addEdge(source - 1, sink, k, 0);
}

bool SPFA(int start, int end) {
    memset(pre, -1, sizeof(pre));
    memset(vis, 0, sizeof(vis));
    memset(dist, -1, sizeof(dist));
    queue<int> Q; Q.push(start);
    int u, v, i; vis[start] = 1; dist[start] = 0;
    while(!Q.empty()) {
        u = Q.front(); Q.pop(); vis[u] = 0;
        for(i = head[u]; i != -1; i = E[i].next) {
            v = E[i].v;
            if(E[i].c && dist[v] < dist[u] + E[i].f) {
                dist[v] = dist[u] + E[i].f;
                pre[v] = i;
                if(!vis[v]) {
                    vis[v] = 1; Q.push(v);
                }
            }
        }
    }
    return dist[end] != -1;
}

void solve() {
    int sum = 0, i, u, v, minCut;
    while(SPFA(source, sink)) {
        minCut = inf;
        for(i = pre[sink]; i != -1; i = pre[E[i].u]) {
            if(minCut > E[i].c) minCut = E[i].c;
        }
        sum += minCut * dist[sink];
        for(i = pre[sink]; i != -1; i = pre[E[i].u]) {
            E[i].c -= minCut;
            E[i^1].c += minCut;
        }
    }
    printf("%d\n", sum);
}

int main() {
    // freopen("stdin.txt", "r", stdin);
    while(scanf("%d%d", &n, &k) == 2) {
        getMap();
        solve();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
百度百科创建词条工具V2.7 我们先了解一下百度百科的优势: 1.权威性,广大网民对百度百科信任度特别高,容易受百科中相关信息影响 2.排名好,绝大部分百科词条(即关键词)能排至各大搜索引擎的前三位 3.流量大,一般词条每天浏览量不亚于一个中型企业站每天的总流量 4.转化率高,百科成为网民上网查资料必看的网站,转化为客户的几率较PPC及PM广告大得多。如病人及其家属查找某疾病如何治疗时,必看百科 5.长期有效,百科广告加上之后长期稳定有效,且不产生后续费用 ………   那么,百度百科创建词条工具可以提供哪些帮助呢? 1.创建百科词条,如品牌名、网站名、产品词、人名、公司名… 2.修改百科词条,在原有词条中加入您的内容,如广告内容、名片… 3.删除百科词条,删除不利词条内容或整个词条(不推荐使用) 4.百科内容撰写,根据客户要求编写词条内容 如有其他需求可及时与客服人员沟通,QQ:120962274 百度百科创建词条网站:www.uducn.com   百度百科创建词条常见错误: 1.修改词条原因不明确。例如:修改原因为“编辑词条”“不具体”“更完善”“更具体”等。 2.修改词条原因错误。例如:修改内容是添加图片,填写的修改原因为添加链接。 3.修改词条原因未能明确说明修改的具体区域。例如:修改了词条中的内容并添加了链接,修改原因应写明:添加内容以及链接,必须指出修改或删除的错误内容,并给出具体理由;只修改错别字,必须指明具体的错字;若您修改了表格中的内容,必须明确指出您修改了表格中的哪部分内容。 4.修改词条不可完全删除原词条的内容,可以选择性删除修改原词条内容。 5.编辑者误将角标误添加在段首,或误添加在了完整段落句号之前。   百度百科创建词条时请注意您的词条中不要有违背“百科原则”的内容,否则词条将被编辑删除,并扣除20分,情节严重者,“百科”有权对其做出关闭部分权限、暂停直至删除其帐号等处罚。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值