zoukankan      html  css  js  c++  java
  • poj 3422 Kaka's Matrix Travels

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

    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

    题意:从正方形矩阵的左上角走到终点右下角,中途只能往右走或者往下走,走到终点算走完一遍,现在棋盘每一个位置上都有相应的数字,走到相应的格子中则累加该数字,之后棋盘上该位置处数字变0。某人按规则一共在棋盘上走完了K次,问走了K次后累加的和sum最大为多少。
    思路:棋盘每个格点可以拆成两个格点来建图,两个格点之间连两条边,一条流量为1,费用开始该格点上的数字的相反数,代表第一次走的时候往这条边走,可以使用一次该点上的数字,另一条边流量K,费用0,代表第二次或者以后再走这条边,就不能再累加该点上的数字。
    之后建立源汇点,求最小费用最大流,求得的是负的最小值,相反数为正的最大值。
    AC代码:
    #define _CRT_SECURE_NO_DEPRECATE
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<vector>
    #include<cstring>
    #include<string>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define INF 0x3f3f3f3f
    const int N_MAX = 50+4, V_MAX = 2*N_MAX*N_MAX+2;
    
    typedef pair<int, int>P;
    struct edge {
        int to, cap, cost, rev;
        edge(int to = 0, int cap = 0, int cost = 0, int rev = 0) :to(to), cap(cap), cost(cost), rev(rev) {}
    };
    int V;
    vector<edge>G[V_MAX];
    int h[V_MAX];
    int dist[V_MAX];
    int prevv[V_MAX], preve[V_MAX];
    
    void add_edge(int from, int to, int cap, int cost) {
        G[from].push_back(edge(to, cap, cost, G[to].size()));
        G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
    }
    //没流量则返回-1
    int min_cost_flow(int s, int t, int f) {
        int res = 0;
        fill(h, h + V, 0);
        while (f>0) {
            priority_queue<P, vector<P>, greater<P> >que;
            fill(dist, dist + V, INF);
            dist[s] = 0;
            que.push(P(0, s));
            while (!que.empty()) {
                P p = que.top(); que.pop();
                int v = p.second;
                if (dist[v] < p.first)continue;
                for (int i = 0; i < G[v].size(); i++) {
                    edge&e = G[v][i];
                    if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(P(dist[e.to], e.to));
                    }
                }
            }
            if (dist[t] == INF)return -1;
            for (int v = 0; v < V; v++)h[v] += dist[v];
            int d = f;
            for (int v = t; v != s; v = prevv[v]) {
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d*h[t];
            for (int v = t; v != s; v = prevv[v]) {
                edge&e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }
    
    void clear() {
        for (int i = 0; i < V; i++) {
            G[i].clear();
        }
    }
    
    int N, K;
    
    int change(int x,int y) {
        return 2 * (N*y + x) + 1;
    }
    
    int main() {
        while (scanf("%d%d",&N,&K)!=EOF) {
            int s = 0, t = 2 * N*N + 1;
            V = t+1;
            add_edge(s,1,K,0);
            add_edge(t - 1, t, K, 0);
            for (int i = 0; i < N;i++) {
                for (int j = 0; j < N;j++) {
                    int a;
                    scanf("%d",&a);
                    int cur = change(i, j);
                    add_edge(cur,cur+1,1,-a);
                    add_edge(cur, cur + 1, K, 0);
                    if (i + 1 < N) {//向下连边
                        int down = change(i + 1, j);
                        add_edge(cur+1,down,K,0);
                    }
                    if (j + 1 < N) {//向右连边
                        int left = change(i,j+1);
                        add_edge(cur+1,left,K,0);
                    }
                }
            }
           
            printf("%d
    ",-min_cost_flow(s,t,K));
            clear();
        }
        return 0;
    }
  • 相关阅读:
    hadoop分布式搭建
    朴素贝叶斯算法
    python数组并集交集补集
    VMware Workstation下安装Linux
    决策树ID3算法
    微信小程序开发测试
    筛法求素数质数
    STL——heap结构及算法
    STL——序列式容器
    使用位图字体工具BMFont从图片生成自定义字体
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/7281846.html
Copyright © 2011-2022 走看看