• poj3422 Kaka's Matrix Travels


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

    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
    题目大意:从左上角走到右下角k次,收集走到的点的数字,每个数字只能收集一次,问最多可以收集多大的数字.
    分析:k=2就是非常经典的dp问题了.k其实就是限制一个点最多只能走k次,网络流可以限制一条边走的次数,那么可以将边的情况变到点的情况上.对于每一个点,拆成两个点,这两个点之间连一条容量为走的次数的限制.因为要求权值,所以求的是费用流.
              容量问题解决了,但是费用问题不是很好办,一个点的数字只能被收集一次,那么最多只允许走一次费用为a[i][j]的边,剩下的k-1次只能走费用为0的边,那么对于每个点a拆成的两个点a',a'',从a'向a''连一条容量为1,费用为a[i][j]的边,再连一条容量为k - 1,费用为0的边,对于每个点被拆出的第二个点a'',向下一个能走到的点b'连一条容量为k,费用为0的边.最后跑最大费用最大流就可以了.在最小费用最大流上将spfa改成求最长路就可以了.
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 50010,inf = 0x3f3f3f3f;
    int n,k,a[60][60],head[maxn],to[maxn],nextt[maxn],tot = 2,w[maxn],c[maxn];
    int S,T,d[maxn],vis[maxn],vis2[maxn],ans;
    
    void add(int x,int y,int z,int p)
    {
        w[tot] = z;
        c[tot] = p;
        to[tot] = y;
        nextt[tot] = head[x];
        head[x] = tot++;
    
        w[tot] = 0;
        c[tot] = -p;
        to[tot] = x;
        nextt[tot] = head[y];
        head[y] = tot++;
    }
    
    bool spfa()
    {
        memset(vis,0,sizeof(vis));
        memset(vis2,0,sizeof(vis2));
        memset(d,-1,sizeof(d));
        queue <int> q;
        vis[S] = 1;
        d[S] = 0;
        q.push(S);
        while (!q.empty())
        {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for (int i = head[u];i;i = nextt[i])
            {
                int v = to[i];
                if (w[i] && d[v] < d[u] + c[i])
                {
                    d[v] = d[u] + c[i];
                    if (!vis[v])
                    {
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        return d[T] != -1;
    }
    
    int dfs(int u,int f)
    {
        if (u == T)
        {
            ans += f * d[u];
            return f;
        }
        int res = 0;
        vis2[u] = 1;
        for (int i = head[u];i;i = nextt[i])
        {
            int v = to[i];
            if (!vis2[v] && w[i] && d[v] == d[u] + c[i])
            {
                int temp = dfs(v,min(f - res,w[i]));
                res += temp;
                w[i] -= temp;
                w[i ^ 1] += temp;
                if (res == f)
                    return res;
            }
        }
        return res;
    }
    
    void dinic()
    {
        while (spfa())
            dfs(S,inf);
    }
    
    int main()
    {
        scanf("%d%d",&n,&k);
        S = 0,T = n * n * 2 + 1;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
            {
                scanf("%d",&a[i][j]);
                int id = (i - 1) * n + j;
                add(id,id + n * n,1,a[i][j]);
                add(id,id + n * n,k - 1,0);
                int tx = i + 1,ty = j;
                if (tx <= n && ty <= n)
                {
                    int nid = (tx - 1) * n + ty;
                    add(id + n * n,nid,k,0);
                }
                tx = i,ty = j + 1;
                if (tx <= n && ty <= n)
                {
                    int nid = (tx - 1) * n + ty;
                    add(id + n * n,nid,k,0);
                }
            }
        add(S,1,k,0);
        add(n * n * 2,T,k,0);
        dinic();
        printf("%d
    ",ans);
    
        return 0;
    }
  • 相关阅读:
    C++11 中的 Defaulted 和 Deleted 函数
    php运行出现Call to undefined function curl_init()的解决方法
    Windows 8 IIS中配置PHP运行环境的方法
    中国天气预报数据API收集
    IIS 6中mimemap属性的默认设置
    使用APPCAN开发移动应用APP心得
    个人建了一个APPCAN移动前端开发交流QQ群258213194
    APPCAN MAS接口之AJAX
    JavaScript与DOM
    如何让网页在浏览器标题栏显示自己制作的图标ico
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8149899.html
Copyright © 2020-2023  润新知