CF1301E-Nanosoft 思维 棋盘DP
这道题最初的想法是,所有的合法图案都由中间的那个核心的四个格子扩展而成,所以想把核心找出来,用数据结构维护,每次找出询问范围内可以扩展最大的核心。
仔细想想这样子可能会涉及到二维的数据结构,可能的复杂度也过高,有些想骗了。
考虑DP,dp[i][j][k]表示,以i,j为右下角,边长为k的正方形中,最大的合法标志大小。
转移,dp[i][j][k] = max(dp[i][j][k - 1],max(dp[i - 1][j][k - 1],max(dp[i][j - 1][k - 1],dp[i - 1][j - 1][k - 1])));
然后考虑i,j带来的影响,只可能是以i,j为右下角构成了边长为k的合法标志,这个我们分颜色二维前缀和判断就可以了。
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 int n,m,q,sum[4][510][510],dp[510][510][510],res; 5 char mp[510][510]; 6 int c2n(char c) 7 { 8 if (c == 'R') 9 return 0; 10 if (c == 'G') 11 return 1; 12 if (c == 'Y') 13 return 2; 14 if (c == 'B') 15 return 3; 16 return -1; 17 } 18 bool check(int x,int y,int l) 19 { 20 if (sum[3][x][y] - sum[3][x - l / 2][y] - sum[3][x][y - l / 2] + sum[3][x - l / 2][y - l / 2] != l * l / 4) 21 return false; 22 if (sum[2][x][y - l / 2] - sum[2][x][y - l] - sum[2][x - l / 2][y - l / 2] + sum[2][x - l / 2][y - l] != l * l / 4) 23 return false; 24 if (sum[1][x - l / 2][y] - sum[1][x - l][y] - sum[1][x - l / 2][y - l / 2] + sum[1][x - l][y - l / 2] != l * l / 4) 25 return false; 26 if (sum[0][x - l / 2][y - l / 2] - sum[0][x - l][y - l / 2] - sum[0][x - l / 2][y - l] + sum[0][x - l][y - l] != l * l / 4) 27 return false; 28 return true; 29 } 30 int main() 31 { 32 scanf("%d%d%d",&n,&m,&q); 33 for (int i = 1;i <= n;i++) 34 scanf("%s",mp[i] + 1); 35 for (int i = 1;i <= n;i++) 36 for (int j = 1;j <= m;j++) 37 { 38 for (int o = 0;o <= 3;o++) 39 sum[o][i][j] = sum[o][i - 1][j] + sum[o][i][j - 1] - sum[o][i - 1][j - 1]; 40 sum[c2n(mp[i][j])][i][j]++; 41 } 42 for (int i = 1;i <= n;i++) 43 for (int j = 1;j <= m;j++) 44 for (int k = 1;k <= min(i,j);k++) 45 { 46 dp[i][j][k] = max(dp[i][j][k - 1],max(dp[i - 1][j][k - 1],max(dp[i][j - 1][k - 1],dp[i - 1][j - 1][k - 1]))); 47 if (!(k & 1) && check(i,j,k)) 48 dp[i][j][k] = k; 49 } 50 int r1,c1,r2,c2; 51 for (int i = 1;i <= q;i++) 52 { 53 res = 0; 54 scanf("%d%d%d%d",&r1,&c1,&r2,&c2); 55 int k = min(r2 - r1 + 1,c2 - c1 + 1); 56 if (r2 - r1 > c2 - c1) 57 { 58 for (int o = r2;o - k + 1 >= r1;o--) 59 { 60 res = max(res,dp[o][c2][k]); 61 } 62 }else 63 { 64 for (int o = c2;o - k + 1 >= c1;o--) 65 { 66 res = max(res,dp[r2][o][k]); 67 } 68 } 69 printf("%d\n",res * res); 70 } 71 return 0; 72 }
心之所动 且就随缘去吧