1227 方格取数 2
时间限制: 1 s空间限制: 128000 KB
题目等级 : 大师 Master
题解
题目描述 Description
给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大输入描述 Input Description
第一行两个数n,k(1<=n<=50, 0<=k<=10)接下来n行,每行n个数,分别表示矩阵的每个格子的数
输出描述 Output Description
一个数,为最大和样例输入 Sample Input
3 11 2 3
0 2 1
1 4 2
样例输出 Sample Output
11数据范围及提示 Data Size & Hint
1<=n<=50, 0<=k<=10
= =拖了半年写出来的题 纪念一下(……) 代码还是基本参考的姜神的(…………)
基本裸的拆点网络流 0 0。。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f;
int N, K;
int map[55][55];
int head[105*105*2];
int k = 0;
int S, T;
int ans = 0;
struct ed
{
int u, v, w, flow, next;
}e[105*105*5];
inline int in(int i, int j)
{
return (((i-1) * N + j) << 1) - 1;
}
inline int out(int i, int j)
{
return ((i-1) * N + j) << 1;
}
inline void adde(int u, int v, int f, int w)
{
e[k] = (ed){u, v, w, f, head[u]};
head[u] = k++;
e[k] = (ed){v, u, -w, 0, head[v]};
head[v] = k++;
}
inline void build_map()
{
memset(head, -1, sizeof(head));
for(int i = 1; i <= N; ++i)
{
for(int j = 1; j <= N; ++j)
{
int In = in(i, j);
int Out = out(i, j);
adde(In, Out, 1, map[i][j]);
adde(In, Out, inf, 0);
if(i < N) adde(Out, in(i+1, j), inf, 0);
if(j < N) adde(Out, in(i, j+1), inf, 0);
}
}
S = 0; T = out(N, N) + 1;
adde(S, in(1, 1), K, 0);
adde(out(N, N), T, K, 0);
}
int dis[105*105*2];
int vis[105*105*2];
int per[105*105*2];
queue <int> q;
bool spfa()
{
memset(dis, -inf, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[S] = 0;
q.push(S);
while(!q.empty())
{
int u = q.front(); q.pop();
vis[u] = 0;
for(int i = head[u]; ~i; i = e[i].next)
{
int v = e[i].v;
if(e[i].flow && dis[v] < dis[u] + e[i].w)
{
per[v] = i;
dis[v] = dis[u] + e[i].w;
if(!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
return dis[T] > 0;
}
int main()
{
cin >> N >> K;
for(int i = 1; i <= N; ++i)
{
for(int j = 1; j <= N; ++j)
{
scanf("%d", &map[i][j]);
}
}
build_map();
while(spfa())
{
int f = inf;
for(int i = T; i != S; i = e[per[i] ^ 1].v)
{
f = min(f, e[per[i]].flow);
}
for(int i = T; i != S; i = e[per[i] ^ 1].v)
{
e[per[i]].flow -= f;
e[per[i] ^ 1].flow += f;
}
ans += f * dis[T];
}
cout << ans << endl;
return 0;
}