ACDREAM 02D 小晴天老师系列——晴天的后花园(暴力专场)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值