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

来源:互联网 发布:2016十大网络用语 编辑:程序博客网 时间:2024/05/22 00:50
Kaka's Matrix Travels
Time Limit: 1000MSMemory Limit: 65536KTotal Submissions: 7097Accepted: 2830

Description

On an N × N chessboard with a non-negative number in each grid, Kaka starts his matrix travels withSUM = 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 toSUM in each grid the rook visited, and replaces it with zero. It is not difficult to know the maximumSUM Kaka can obtain for his first travel. Now Kaka is wondering what is the maximumSUM he can obtain after his Kth travel. Note the SUM is accumulative during theK travels.

Input

The first line contains two integers N andK (1 ≤ N ≤ 50, 0 ≤ K ≤ 10) described above. The followingN 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 hisKth travel.

Sample Input

3 21 2 30 2 11 4 2

Sample Output

15

Source

POJ Monthly--2007.10.06, Huang, Jinsong
 
 
【题目大意】:
        给出一个正方型网格,每个小方格中有一个非负数,现在从左上角走到右下角,每次走一步,只能往右或往下走,经过的数字拿走,每次都找可以拿到数字和最大的路径走,且在一个方格走过一次后,上边的数字就变为0。现在走K次,求最大获得权值综合。
【分析】:
        费用流基本模型:拆点。首先建图。我们将每一个点拆成两个点,一个原点,一个出点。先将这个点的原点和出点之间建两条边,其中一条流量为1,费用为当前位置的数字的相反数,另一条流量为K-1,费用为0。然后将每个格子的出点与其右边的格子的原点及下边的原点建一条边,流量为K,费用为0。另建一超级源点与第一个格子的原点连流量为K,费用为0的边,最后一个格子的出点和超级汇点连流量为K,费用为0的边。最后跑一遍最小费用流,答案为最小费用的相反数。
【代码】:
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<algorithm>#include<iostream>#include<queue>using namespace std;#define MAX 100#define MAXN 100001#define MAXE 1000001#define IMAX 21474836struct GROUPS{int f,t,flow,cost,next;};GROUPS a[MAXE];int N,K,map[MAX][MAX],tot=0,last[MAXN],dist[MAXN],ans=0,fa[MAXN];bool vis[MAXN];void add(int from,int to,int cost,int flow){      a[tot].f=from;      a[tot].t=to;      a[tot].next=last[from];      a[tot].flow=flow;      a[tot].cost=cost;      last[from]=tot++;            a[tot].f=to;      a[tot].t=from;      a[tot].next=last[to];      a[tot].flow=0;      a[tot].cost=-cost;      last[to]=tot++;      }void pre_group(){      for(int i=1;i<=N;i++)            for(int j=1;j<=N;j++)            {                  int getnum=(i-1)*N+j;                  add(getnum,N*N+getnum,-map[i][j],1);                  add(getnum,N*N+getnum,0,K-1);            }      for(int i=1;i<N;i++)//down to conect            for(int j=1;j<=N;j++)            {                  int nextnum=i*N+j;                  int nownum=(i-1)*N+j;                  add(N*N+nownum,nextnum,0,K);            }      for(int i=1;i<=N;i++)//right to conect            for(int j=1;j<N;j++)            {                  int nextnum=(i-1)*N+j+1;                  int nownum=(i-1)*N+j;                  add(N*N+nownum,nextnum,0,K);            }      add(0,1,0,K);      add(2*N*N,2*N*N+1,0,K);          }bool spfa(){      queue<int> Q;      for(int i=0;i<=2*N*N+1;i++)            dist[i]=IMAX;      memset(fa,-1,sizeof(fa));      memset(vis,false,sizeof(vis));      dist[0]=0;      vis[0]=true;      Q.push(0);      while(!Q.empty())      {            int now=Q.front();            Q.pop();            for(int i=last[now];i!=-1;i=a[i].next)            {                  int to=a[i].t;                  if(dist[now]+a[i].cost<dist[to] && a[i].flow)                  {                        dist[to]=dist[now]+a[i].cost;                        fa[to]=i;                        if(!vis[to])                        {                              vis[to]=true;                              Q.push(to);                        }                  }            }            vis[now]=false;      }      if(dist[2*N*N+1]==IMAX)   return false;      return true;}void work(){      while(spfa())      {            int minflow=IMAX;            for(int i=fa[2*N*N+1];i!=-1;i=fa[a[i].f])                  minflow=minflow>a[i].flow?a[i].flow:minflow;            for(int i=fa[2*N*N+1];i!=-1;i=fa[a[i].f])            {                  a[i].flow-=minflow;                  a[i^1].flow+=minflow;            }            ans+=dist[2*N*N+1]*minflow;      }}int main(){      //freopen("input.in","r",stdin);  //freopen("output.out","w",stdout);   memset(last,-1,sizeof(last));  scanf("%d%d",&N,&K);  for(int i=1;i<=N;i++)        for(int j=1;j<=N;j++)              scanf("%d",&map[i][j]);      pre_group();      work();      printf("%d",-ans);  //system("pause");      return 0;}

转载注明出处:http://blog.csdn.net/u011400953
0 0