您的位置:首页 > 其它

【费用流】codevs1227 方格取数 2

2015-02-04 21:58 267 查看

 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 1

1 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: