poj 3422 Kaka's Matrix Travels

来源:互联网 发布:蜂窝数据打不开 编辑:程序博客网 时间:2024/05/24 23:16
Kaka's Matrix Travels
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 9453 Accepted: 3840

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 21 2 30 2 11 4 2

Sample Output

15

Source

POJ Monthly--2007.10.06, Huang, Jinsong

提示

题意:

有个n*n(1<=n<=50)带数值的矩阵,左上角是起点,右下角是终点,只能向下或向右,走过一次的地方数值就为零,问走k(0<=k<=10)次最多能得到多少数值。

思路:

看了别人的代码整理出来的,实际上并没有理解透彻。。。

1.拆点,一个点拆成两个,一个是只能走过一次的且带值的点(编号i),另一个就是值为0可以走k次或无限次的点(编号n*n+i)。

2.每个点(以值为0的点为基准)与下边和右边的点(这里又以带值的点为基准)建立边,这样一个图就完成了。不过还需要添加超级源点和终点。

3.因为是求最大值所以最短路算法要改成最长路。

步骤可以理解,还有部分细节还是不很清楚,看样子还有得学。。。

示例程序

Source CodeProblem: 3422Code Length: 2138BMemory: 1608KTime: 63MSLanguage: GCCResult: Accepted#include <stdio.h>#include <string.h>struct{    int v,next,cost,num,pos;}w[20000];int h[5002],numw,map[50][50],n,k,pre[5002];void insert(int u,int v,int cost,int num){    w[numw].v=v;    w[numw].cost=cost;    w[numw].next=h[u];    w[numw].num=num;    w[numw].pos=numw+1;//pos貌似是与反向边建立对应关系    h[u]=numw;    numw++;    w[numw].v=u;//反向边    w[numw].cost=-cost;    w[numw].next=h[v];    w[numw].num=0;    w[numw].pos=numw-1;    h[v]=numw;    numw++;}int spfa(){    int i,q[200000],v[5002],d[5002],pos,f=0,top=0;    memset(v,0,sizeof(v));    memset(d,-1,sizeof(d));    d[0]=0;    v[0]=1;    q[top]=0;    top++;    while(f<top)    {        v[q[f]]=0;        for(i=h[q[f]];i!=-1;i=w[i].next)        {            pos=w[i].v;            if(w[i].num!=0&&d[pos]<d[q[f]]+w[i].cost)            {                d[pos]=d[q[f]]+w[i].cost;                pre[pos]=i;                if(v[pos]==0)                {                    q[top]=pos;                    top++;                    v[pos]=1;                }            }        }        f++;    }    if(d[2*n*n+1]!=-1)    {        return 1;    }    else    {        return 0;    }}int maxflow(){    int i,pos,sum=0;    while(spfa()==1)    {        for(i=2*n*n+1;i!=0;i=w[w[pos].pos].v)        {            pos=pre[i];            w[pos].num=w[pos].num-1;//似乎因为流量固定为一的关系少了循环判断            w[w[pos].pos].num=w[w[pos].pos].num+1;            sum=sum+w[pos].cost;        }    }    return sum;}int main(){    int i,i1,x,y;    scanf("%d %d",&n,&k);    memset(h,-1,sizeof(h));    numw=0;    for(i=0;n>i;i++)    {        for(i1=0;n>i1;i1++)        {            scanf("%d",&map[i][i1]);        }    }    for(i=0;n>i;i++)    {        for(i1=0;n>i1;i1++)        {            x=i*n+i1+1;            y=n*n+x;            insert(x,y,map[i][i1],1);//拆点,加边            insert(x,y,0,k);            if(i!=n-1)//矩阵连边            {                insert(y,x+n,0,k);            }            if(i1!=n-1)            {                insert(y,x+1,0,k);            }        }    }    insert(0,1,0,k);//增加汇点    insert(2*n*n,2*n*n+1,0,k);    printf("%d",maxflow());    return 0;}

0 0
原创粉丝点击