HDU 4328 Cut the Cake(动态规划)

来源:互联网 发布:电脑cpu降温软件 编辑:程序博客网 时间:2024/05/22 01:45


Problem Description
Mark bought a huge cake, because his friend ray_sun’s birthday is coming. Mark is worried about how to divide the cake since it’s so huge and ray_sun is so strange. Ray_sun is a nut, you can never imagine how strange he was, is, and going to be. He does not eat rice, moves like a cat, sleeps during work and plays games when the rest of the world are sleeping……It is not a surprise when he has some special requirements for the cake. A considering guy as Mark is, he will never let ray_sun down. However, he does have trouble fulfilling ray_sun’s wish this time; could you please give him a hand by solving the following problem for him?
  The cake can be divided into n*m blocks. Each block is colored either in blue or red. Ray_sun will only eat a piece (consisting of several blocks) with special shape and color. First, the shape of the piece should be a rectangle. Second, the color of blocks in the piece should be the same or red-and-blue crisscross. The so called ‘red-and-blue crisscross’ is demonstrated in the following picture. Could you please help Mark to find out the piece with maximum perimeter that satisfies ray_sun’s requirements?

 

Input
The first line contains a single integer T (T <= 20), the number of test cases.
  For each case, there are two given integers, n, m, (1 <= n, m <= 1000) denoting the dimension of the cake. Following the two integers, there is a n*m matrix where character B stands for blue, R red.
 

Output
For each test case, output the cased number in a format stated below, followed by the maximum perimeter you can find.
 

Sample Input
21 1B3 3BBRRBBBBB
 

Sample Output
Case #1: 4Case #2: 8
 


#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 1111;int tcase, n, m;int h[maxn][maxn];int L[maxn], R[maxn];char cake[maxn][maxn];int ans;void dealBlue(){memset(h, 0, sizeof(h));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {if (cake[i][j] == 'B') {h[i][j] = h[i-1][j] + 1;} else {h[i][j] = 0;}}}for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {L[j] = R[j] = j;}for (int j = 1; j <= m; ++j) {while (L[j] > 1 && h[i][L[j]-1] >= h[i][j]) {L[j] = L[L[j]-1];}}for (int j = m; j >= 1; --j) {while (R[j] < m && h[i][R[j]+1] >= h[i][j]) {R[j] = R[R[j]+1];}}for (int j = 1; j <= m; ++j) {if (h[i][j] != 0) { // 刚开始没加这个判断,WA了一次。下面两个也一样 ans = max(ans, (R[j] - L[j] + 1 + h[i][j]) * 2);}//printf("BLUE:%d\n", ans);}}}void dealRed(){memset(h, 0, sizeof(h));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {if (cake[i][j] == 'R') {h[i][j] = h[i-1][j] + 1;} else {h[i][j] = 0;}}}for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {L[j] = R[j] = j;}for (int j = 1; j <= m; ++j) {while (L[j] > 1 && h[i][L[j]-1] >= h[i][j]) {L[j] = L[L[j]-1];}}for (int j = m; j >= 1; --j) {while (R[j] < m && h[i][R[j]+1] >= h[i][j]) {R[j] = R[R[j]+1];}}for (int j = 1; j <= m; ++j) {if (h[i][j] != 0) {ans = max(ans, (R[j] - L[j] + 1 + h[i][j]) * 2);}//printf("RED:%d\n", ans);}}}void dealBlue_Red(){memset(h, 0, sizeof(h));for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m;  ++j) {if (cake[i][j] != cake[i-1][j]) {h[i][j] = h[i-1][j] + 1;} else {h[i][j] = 1;}}}for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {L[j] = R[j] = j;}for (int j = 1; j <= m; ++j) {while (L[j] > 1 && h[i][L[j]-1] >= h[i][j] && cake[i][L[j]-1] != cake[i][L[j]]) {L[j] = L[L[j]-1];}}for (int j = m; j >= 1; --j) {while (R[j] < m && h[i][R[j]+1] >= h[i][j] && cake[i][R[j]+1] != cake[i][R[j]]) {R[j] = R[R[j]+1];}}for (int j = 1; j <= m; ++j) {if (h[i][j] != 0) {ans = max(ans, (R[j] - L[j] + 1 + h[i][j]) * 2);}//printf("RED&BLUE:%d\n", ans);}}}int main(){scanf("%d", &tcase);for (int cas = 1; cas <= tcase; ++cas) {scanf("%d%d", &n, &m);getchar();for (int i = 1; i <= n; ++i) {for (int j = 1; j <= m; ++j) {cake[i][j] = getchar();}getchar();}ans = -1;dealBlue();dealRed();dealBlue_Red();printf("Case #%d: %d\n", cas, ans); }return 0;}


原创粉丝点击