ACDREAM 02D 小晴天老师系列——晴天的后花园
Problem Description
小晴天非常漂亮的后花园,打算以后退休之后在里面种种花,养养草,所以现在小晴天打算为他的后花园围上栅栏。
小晴天的后花园可以看成是一个m*n的矩形,但是其中有一些地方种了树,这些地方都不能安装栅栏,现在小晴天把后花园的平面图告诉你了,请你帮忙设计一个最大的矩形栅栏。
Input
单组数据,第一行包括两个整数m,n(1<=m,n<=500),接下来m行,每行包括n个字符,仅由’x’和’.’组成(ASCII码分别是120与46).
其中‘x’表示这个方格有树木,‘.’表示这个点可以建造栅栏
Output
若可以围成一个闭合栅栏,输出一个整数,表示栅栏能打到的最大周长
否则输出impossible
Sample Input
4 5
…..
.x.x.
…..
…..
2 2
.x
x.
2 5
…..
xxxx.
Sample Output
14
impossible
impossible
解题思路:遍历栅栏左上角的点,然后找出该点最右和最下的位置(不断缩小),开始判断能否围成矩形。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#define N 505
using namespace std;
typedef long long ll;
char map[N][N];
int n, m, ans;
int mostleft(int x, int y) {
int cnt = 0;
for (int i = y + 1; i < m; i++) {
if (map[x][i] == '.') cnt++;
else break;
}
return cnt;
}
int mostdown(int x, int y) {
int cnt = 0;
for (int i = x + 1; i < n; i++) {
if (map[i][y] == '.') cnt++;
else break;
}
return cnt;
}
int check(int x1, int y1, int x2, int y2) {
for (int i = x1 + 1; i <= x2; i++) {
if (map[i][y1] == 'x') return 0;
}
for (int i = y2 + 1; i <= y1; i++) {
if (map[x2][i] == 'x') return 0;
}
return 1;
}
int main() {
while (scanf("%d %d\n", &n, &m) == 2) {
for (int i = 0; i < n; i++) {
scanf("%s", map[i]);
}
ans = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (map[i][j] == '.') {
int x1 = i, y1 = j + mostleft(i, j);
int x2 = i + mostdown(i, j), y2 = j;
for (int a = j + 1; a <= y1; a++) {
for (int b = i + 1; b <= x2; b++) {
if (check(x1, a, b, y2)) {
ans = max(ans, 2 * ((a - j) + (b - i)));
}
}
}
}
}
}
if (ans) printf("%d\n", ans);
else printf("impossible\n");
}
return 0;
}