标签:
土豪聪要请客
2 2 .. ..
输出示例1
7
输入示例2
4 5 ..X.. .X... X.... .....
输出示例2
11
上一题是CZY的MZ,这题变成聪哥的了……
先明确一下题意,智商捉急的我看了半天样例才理解:地图中选一个周长最大的只包含字符‘.’的矩形,使矩形周长最大,答案是这个最大的周长-1.
我的思路是这样的:枚举上下边界,于是可以把二维的地图压缩成一维的(只要当前列有障碍物X就压成一个‘X’,没有就压成一个‘.’,如样例2地图中,当前枚举到2~4行,那么压缩后的地图变为“XX...”)。压缩成一维后,问题转化为“在一个只包含字符X和字符.的字符串中,选一个尽量长的只包含字符‘.’的连续子串”,因为是连续的,左右端点构成一个滑动窗口,可以用“尺取法”(个人习惯的叫法,详见代码)解决。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); } return x * f; } #define maxn 410 #define INF 1073741823 int n, m, l, r, ans, S[maxn][maxn]; char Map[maxn][maxn]; bool can[maxn]; int main() { n = read(); m = read(); for(int i = 1; i <= n; i++) scanf("%s", Map[i] + 1); for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) S[i][j] = S[i-1][j] + (Map[i][j] == ‘X‘); for(int i = 1; i <= n; i++) for(int j = i; j <= n; j++) { memset(can, 0, sizeof(can)); for(int k = 1; k <= m; k++) can[k] = !(S[j][k] - S[i-1][k]); l = 1; int tmp = -INF; for(r = 1; r <= m; r++) if(!can[r]) l = r + 1; else tmp = max(tmp, r - l + 1); ans = max(ans, (tmp + j - i + 1 << 1) - 1); } printf("%d\n", ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/4926194.html