标签:
Problem Description
欢迎来到珠海!由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展。作为Z市的决策人,在仔细观察了Z市地图之后,你准备通过填充某些海域来扩展Z市的海岸线到最长,来吸引更多的游客前来旅游度假。为了简化问题,假设地图为一个N*M的格子,其中一些是陆地,一些是可以填充的浅海域,一些是不可填充的深海域。这里定义海岸线的长度为一个联通块陆地(可能包含浅海域填充变为的陆地)的边缘长度,两个格子至少有一个公共边,则视为联通。
值得注意的是,这里Z市的陆地区域可以是不联通的,并且整个地图都处在海洋之中,也就是说,Z市是由一些孤岛组成的,比如像,夏威夷?
你的任务是,填充某些浅海域,使得所有岛屿的海岸线之和最长。
Input
输入第一行为T,表示有T组测试数据。
每组数据以两个整数N和M开始,表示地图的规模。接下来的N行,每一行包含一个长度为M的字符串,表示地图,‘.’表示陆地,’E’表示浅海域,’D’表示深海域。[Technical Specification]
- 1 <= T <= 100
- 1 <= N, M <= 47
Output
对每组数据,先输出为第几组数据,然后输出最长的海岸线长度。Sample Input
3
2 2
EE
EE
3 3
EEE
.E.
EEE
3 3
EEE
DED
EEESample Output
Case 1: 8
Case 2: 16
Case 3: 20
Hint
对于第三组样例,一种可行方案是:.E.
D.D
.E.这样5个孤立小岛的海岸线总长为4 * 5 = 20。
我还被Claris坑了..
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
const int Maxn = 50;
const int dx[4] = { 0, 1, 0, -1 };
const int dy[4] = { 1, 0, -1, 0 };
struct node {
int x, y, next, c, opp;
}a[Maxn*Maxn*20]; int first[Maxn*Maxn], len;
int _min ( int x, int y ){ return x < y ? x : y; }
void ins ( int x, int y, int c ){
len ++; int k1 = len;
a[len].x = x; a[len].y = y; a[len].c = c;
a[len].next = first[x]; first[x] = len;
len ++; int k2 = len;
a[len].x = y; a[len].y = x; a[len].c = 0;
a[len].next = first[y]; first[y] = len;
a[k1].opp = k2;
a[k2].opp = k1;
}
int st, ed, h[Maxn*Maxn];
int n, m;
char s[Maxn][Maxn];
int getnum ( int x, int y ){ return (x-1)*m+y; }
bool bfs (){
queue <int> q;
memset ( h, -1, sizeof (h) ); h[st] = 0;
q.push (st);
while ( !q.empty () ){
int x = q.front (); q.pop ();
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( h[y] == -1 && a[k].c > 0 ){
h[y] = h[x]+1;
q.push (y);
}
}
}
return h[ed] > 0;
}
int dfs ( int x, int flow ){
if ( x == ed ) return flow;
int delta = 0;
for ( int k = first[x]; k; k = a[k].next ){
int y = a[k].y;
if ( h[y] == h[x]+1 && a[k].c > 0 && flow-delta > 0 ){
int minf = dfs ( y, _min ( a[k].c, flow-delta ) );
delta += minf;
a[k].c -= minf;
a[a[k].opp].c += minf;
}
}
if ( delta == 0 ) h[x] = -1;
return delta;
}
int main (){
int i, j, k, T, Ti;
scanf ( "%d", &T );
Ti = 0;
while ( T -- ){
scanf ( "%d%d", &n, &m );
len = 0; memset ( first, 0, sizeof (first) );
for ( i = 1; i <= n; i ++ ) scanf ( "%s", s[i]+1 );
for ( i = 0; i <= n+1; i ++ ) s[i][0] = s[i][m+1] = ‘D‘;
for ( i = 0; i <= m+1; i ++ ) s[0][i] = s[n+1][i] = ‘D‘;
int sum = 0;
st = 0; ed = n*m+1;
for ( i = 1; i <= n; i ++ ){
for ( j = 1; j <= m; j ++ ){
if ( s[i][j] == ‘D‘ || s[i][j] == ‘.‘ ){
for ( k = 0; k < 4; k ++ ){
int ii = i+dx[k], jj = j+dy[k];
if ( s[i][j] == s[ii][jj] ){
sum ++;
if ( ii == 0 || ii == n+1 || jj == 0 || jj == m+1 ) sum ++;
}
}
}
else {
int sl = 0, sh = 0;
for ( k = 0; k < 4; k ++ ){
int ii = i+dx[k], jj = j+dy[k];
if ( s[ii][jj] == ‘D‘ ) sh ++;
else if ( s[ii][jj] == ‘.‘ ) sl ++;
else ins ( getnum (i,j), getnum (ii,jj), 1 );
}
if ( (i+j) % 2 == 1 ) ins ( st, getnum (i,j), sl ), ins ( getnum (i,j), ed, sh );
else ins ( st, getnum (i,j), sh ), ins ( getnum (i,j), ed, sl );
}
}
}
int ans = 0, delta;
while ( bfs () ){
while ( delta = dfs ( st, 0x7fffffff ) ) ans += delta;
}
printf ( "Case %d: %d\n", ++Ti, n*(m+1)+(n+1)*m-ans-sum/2 );
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/ra1nbow_chan/article/details/51366777