| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 9961 | Accepted: 4049 |
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
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<stack>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
typedef long long ll;
using namespace std;
#define MV 15000
#define INF 0x3f3f3f3f
int a[55][55];
struct edge{
int to,cap,cost,rev;
};
vector<edge>G[MV];
int dis[MV];
int preve[MV],prevv[MV];
int min_cost_flow(int v,int s,int t,int f)
{
int ans=0,i,j;
while(f>0)
{
fill(dis,dis+v,INF);
dis[s]=0;
bool update=true;
while(update)
{
update=false;
for(i=0;i<v;i++)
{
if(dis[i]==INF)
continue;
int size1=G[i].size();
for(j=0;j<size1;j++)
{
edge &es=G[i][j];
if(es.cap>0&&dis[es.to]>dis[i]+es.cost)
{
dis[es.to]=dis[i]+es.cost;
preve[es.to]=j;
prevv[es.to]=i;
update=true;
}
}
}
}
if(dis[t]==INF)
{
return -1;
}
int d=f;
for(i=t;i!=s;i=prevv[i])
{
d=min(d,G[prevv[i]][preve[i]].cap);
}
f-=d;
ans+=d*dis[t];
for(i=t;i!=s;i=prevv[i])
{
edge &es=G[prevv[i]][preve[i]];
es.cap-=d;
G[es.to][es.rev].cap+=d;
}
}
return ans;
}
void addedge(int s,int t,int cap,int cost)
{
edge es;
es.to=t;
es.cap=cap;
es.cost=cost;
es.rev=G[t].size();
G[s].push_back(es);
es.to=s;
es.cap=0;
es.cost=-cost;
es.rev=G[s].size()-1;
G[t].push_back(es);
}
int main()
{
int v, s, t, f;
int i,j;
int n,k;
while(scanf("%d%d",&n,&k)==2)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&a[i][j]);
}
}
for(i=0;i<MV;i++)
{
G[i].clear();
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
addedge(i*n+j, i*n+j+n*n, 1, -a[i][j]);
addedge(i*n+j, i*n+j+n*n, k, 0);
if(i<n-1)
{
addedge(i*n+j+n*n, (i+1)*n+j, k, 0);
}
if(j<n-1)
{
addedge(i*n+j+n*n, i*n+j+1, k , 0);
}
}
}
s=(n-1)*n+n-1+n*n+1;
t=s+1;
addedge(s, 0, k, 0);
addedge(t-2, t, k, 0);
int tt=-min_cost_flow(t+1,s, t, k);
printf("%d\n",tt);
}
return 0;
}

本文介绍了一个关于寻找矩阵中最大累积值路径的问题。通过多次旅行更新矩阵中的数值,并利用最小费用流算法解决这一挑战。文章提供了详细的算法实现,包括拆点技巧和具体的代码示例。
1075

被折叠的 条评论
为什么被折叠?



