• 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
    ",res * res);
    70     }
    71     return 0;
    72 }
  • 相关阅读:
    FastAPI(60)- 针对 WebSocket 进行单元测试
    FastAPI(59)- 详解使用 OAuth2PasswordBearer + JWT 认证
    FastAPI(58)- 使用 OAuth2PasswordBearer 的简单栗子
    FastAPI(57)- 安全相关的概念
    FastAPI(56)- 使用 Websocket 打造一个迷你聊天室
    FastAPI(55)- Events: startup
    FastAPI(54)- 详解 Request 请求对象
    FastAPI(53)- Response Headers 响应设置 Headers
    FastAPI(52)- Response Cookies 响应设置 Cookies
    FastAPI(51)- 自定义响应之 StreamingResponse、FileResponse
  • 原文地址:https://www.cnblogs.com/iat14/p/12315694.html
Copyright © 2020-2023  润新知