POJ 3422 Kaka's Matrix Travels

Kaka's Matrix Travels

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 9570   Accepted: 3891

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 Ktravels.

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

题意:

给出一个网格图,每个点有权值,要求从(1,1)走到(n,n),路程的权值就是走过的格子的权值,但是一旦经过了这个格子,这个格子的权值就变为了0,要求走k次,使得前k次的权值之和最大...

分析:

最大费用最大流

我们要满足每个格子的权值只能被取一次,所以拆点,从入点到出点连一条容量为1费用为-val的边,但是又可以经过k次,所以要再连一条容量为k,费用为0的边,然后每个格子想右边和下边的格子连边,S设为(1,1),T设为(n,n)...跑最小费用最大流就好了...

代码:

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 //by NeighThorn
 7 #define inf 0x3f3f3f3f
 8 using namespace std;
 9 //大鹏一日同风起,扶摇直上九万里 
10 
11 const int maxn=5000+5,maxm=maxn*10+5;
12 
13 int n,k,S,T,cnt,w[maxm],hd[maxn],fl[maxm],to[maxm],nxt[maxm],dis[maxn],Min[maxn],vis[maxn],from[maxn],mp[50+5][50+5];
14 
15 inline bool spfa(void){
16     memset(dis,inf,sizeof(dis));
17     memset(Min,inf,sizeof(Min));
18     queue<int> q;q.push(S);vis[S]=1,dis[S]=0;
19     while(!q.empty()){
20         int top=q.front();q.pop();vis[top]=0;
21         for(int i=hd[top];i!=-1;i=nxt[i])
22             if(dis[to[i]]>dis[top]+w[i]&&fl[i]){
23                 from[to[i]]=i;
24                 dis[to[i]]=dis[top]+w[i];
25                 Min[to[i]]=min(Min[top],fl[i]);
26                 if(!vis[to[i]])
27                     vis[to[i]]=1,q.push(to[i]);
28             }
29     }
30     return dis[T]!=inf; 
31 }
32 
33 inline int find(void){
34     for(int i=T;i!=S;i=to[from[i]^1])
35         fl[from[i]]-=Min[T],fl[from[i]^1]+=Min[T];
36     return Min[T]*dis[T];
37 }
38 
39 inline int dinic(void){
40     int res=0;
41     while(spfa())
42         res+=find();
43     return res;
44 }
45 
46 inline void add(int l,int s,int x,int y){
47     w[cnt]=l;fl[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
48     w[cnt]=-l;fl[cnt]=0;to[cnt]=x;nxt[cnt]=hd[y];hd[y]=cnt++;
49 }
50 
51 signed main(void){
52     memset(hd,-1,sizeof(hd));
53     scanf("%d%d",&n,&k);
54     for(int i=1;i<=n;i++)
55         for(int j=1;j<=n;j++)
56             scanf("%d",&mp[i][j]);
57     for(int i=1;i<=n;i++)
58         for(int j=1;j<=n;j++){
59             add(-mp[i][j],1,(i-1)*n+j,(i-1)*n+j+n*n),add(0,k,(i-1)*n+j,(i-1)*n+j+n*n);
60             if(i+1<=n)
61                 add(0,k,(i-1)*n+j+n*n,i*n+j);
62             if(j+1<=n)
63                 add(0,k,(i-1)*n+j+n*n,(i-1)*n+j+1);
64         }
65     S=0;add(0,k,S,1);T=n*n+n*n;
66     printf("%d\n",-dinic());
67     return 0;
68 }//Cap ou pas cap. Cap.
View Code

By NeighThorn

posted @ 2016-12-30 09:55  NeighThorn  阅读(219)  评论(0编辑  收藏  举报