zoukankan      html  css  js  c++  java
  • agc033

    A题意:给你个黑白矩阵,每次黑的周围一圈会变黑,求多少次之后全黑。n <= 1000

    解:BFS即可。

     1 #include <bits/stdc++.h>
     2  
     3 const int N = 1010;
     4 const int dx[] = {1, 0, -1, 0};
     5 const int dy[] = {0, 1, 0, -1};
     6  
     7 struct Node {
     8     int x, y;
     9     Node(int X = 0, int Y = 0) {
    10         x = X;
    11         y = Y;
    12     }
    13 };
    14  
    15 int vis[N][N], d[N][N];
    16 char str[N];
    17 std::queue<Node> Q;
    18  
    19 int main() {
    20  
    21     int n, m, ans = 0;
    22     scanf("%d%d", &n, &m);
    23     for(int i = 1; i <= n; i++) {
    24         scanf("%s", str + 1);
    25         for(int j = 1; j <= m; j++) {
    26             if(str[j] == '#') {
    27                 Q.push(Node(i, j));
    28                 vis[i][j] = 1;
    29                 d[i][j] = 0;
    30             }
    31         }
    32     }
    33  
    34     while(Q.size()) {
    35         int x = Q.front().x, y = Q.front().y;
    36         Q.pop();
    37         for(int i = 0; i < 4; i++) {
    38             int tx = x + dx[i], ty = y + dy[i];
    39             if(tx < 1 || ty < 1 || tx > n || ty > m || vis[tx][ty]) {
    40                 continue;
    41             }
    42             vis[tx][ty] = 1;
    43             d[tx][ty] = d[x][y] + 1;
    44             Q.push(Node(tx, ty));
    45             ans = std::max(ans, d[tx][ty]);
    46         }
    47     }
    48     printf("%d
    ", ans);
    49     return 0;
    50 }
    AC代码

    B题意:给你个矩阵,初始时有个棋子在(sx,sy)。先后手都有个字符串,每一回合可以选择不走或者按照字符串上的方向走一步。先手想要玩完n回合,后手想要在n回合之内把棋子走出棋盘。谁能如愿以偿呢?n <= 20w

    解:发现行列独立。于是考虑行。我们从后往前,维护第i步时棋子在哪些地方会导致在n步内出棋盘。判断一下是否必出棋盘即可。列同理。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 200010;
     4 
     5 char str1[N], str2[N];
     6 int n;
     7 
     8 int main() {
     9 
    10     int n1, n2, x1, x2;
    11     scanf("%d%d%d", &n1, &n2, &n);
    12     scanf("%d%d", &x1, &x2);
    13     scanf("%s%s", str1 + 1, str2 + 1);
    14 
    15     bool f = 1;
    16     int L = 0, R = n1 + 1;
    17     for(int i = n; i >= 1; i--) {
    18 
    19         if(str2[i] == 'L' || str2[i] == 'R') {
    20 
    21         }
    22         else if(str2[i] == 'D') {
    23             L = std::max(L - 1, 0);
    24         }
    25         else {
    26             R = std::min(R + 1, n1 + 1);
    27         }
    28 
    29         if(str1[i] == 'L' || str1[i] == 'R') {
    30 
    31         }
    32         else if(str1[i] == 'D') {
    33             R = R - 1;
    34         }
    35         else {
    36             L = L + 1;
    37         }
    38         if(L + 1 >= R) {
    39             f = 0;
    40             break;
    41         }
    42 
    43     }
    44     if(x1 <= L || R <= x1) {
    45         f = 0;
    46     }
    47     L = 0, R = n2 + 1;
    48     for(int i = n; i >= 1 && f; i--) {
    49 
    50         if(str2[i] == 'U' || str2[i] == 'D') {
    51 
    52         }
    53         else if(str2[i] == 'L') {
    54             R = std::min(R + 1, n2 + 1);
    55         }
    56         else {
    57             L = std::max(L - 1, 0);
    58         }
    59 
    60         if(str1[i] == 'U' || str1[i] == 'D') {
    61 
    62         }
    63         else if(str1[i] == 'L') {
    64             L = L + 1;
    65         }
    66         else {
    67             R = R - 1;
    68         }
    69         if(L + 1 >= R) {
    70             f = 0;
    71             break;
    72         }
    73 
    74     }
    75     if(x2 <= L || R <= x2) {
    76         f = 0;
    77     }
    78     if(f) {
    79         printf("YES
    ");
    80     }
    81     else {
    82         printf("NO
    ");
    83     }
    84     return 0;
    85 }
    AC代码

    C题意:给你一棵树,每个点上有一个硬币。两个人轮流选择一个有硬币的点,把该点的硬币取走并把其它点的硬币都向这个点挪一步。不能操作者输。问谁输?n <= 20w

    解:发现与每个点的具体硬币数量没关系,只跟是否有硬币有关系。然后发现每一次就是删掉所有叶子,但是你可以选择保护一个叶子不被删。我们感性想象一下,发现跟每某个点的伸出去的最长链有关系...

    然后考虑直径,别问我怎么想到的...灵光一闪就想到了。发现每次操作之后,直径要么减2要么减1,就算直径改变了,但是长度仍然遵守这个规律。且最后剩下来的是一条单个的直径。于是求出直径长度,sg函数即可。(其实有个规律......) 

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 200010;
     4 
     5 struct Edge {
     6     int nex, v;
     7 }edge[N << 1]; int tp;
     8 
     9 int n, e[N], sg[N], f[N], Ans;
    10 
    11 inline void add(int x, int y) {
    12     edge[++tp].v = y;
    13     edge[tp].nex = e[x];
    14     e[x] = tp;
    15     return;
    16 }
    17 
    18 void DFS(int x, int fa) {
    19     int a = 1, b = 0;
    20     for(int i = e[x]; i; i = edge[i].nex) {
    21         int y = edge[i].v;
    22         if(y == fa) continue;
    23         DFS(y, x);
    24         if(a < f[y] + 1) {
    25             b = a;
    26             a = f[y] + 1;
    27         }
    28         else {
    29             b = std::max(b, f[y] + 1);
    30         }
    31     }
    32     Ans = std::max(Ans, std::max(a + b - 1, a));
    33     f[x] = a;
    34     return;
    35 }
    36 
    37 int main() {
    38 
    39     int n;
    40     scanf("%d", &n);
    41     for(int i = 1, x, y; i < n; i++) {
    42         scanf("%d%d", &x, &y);
    43         add(x, y);
    44         add(y, x);
    45     }
    46 
    47     DFS(1, 0);
    48 
    49     /// cal Ans
    50     sg[1] = 1;
    51     sg[2] = 0;
    52     for(int i = 3; i <= Ans; i++) {
    53         if(std::min(sg[i - 1], sg[i - 2]) == 0) {
    54             sg[i] = 1;
    55         }
    56         else {
    57             sg[i] = 0;
    58         }
    59     }
    60 
    61     if(sg[Ans]) {
    62         printf("First
    ");
    63     }
    64     else {
    65         printf("Second
    ");
    66     }
    67 
    68     return 0;
    69 }
    AC代码

    D题意:给你一个黑白矩阵,求它的复杂度。定义一个矩阵的复杂度为:纯色矩阵为0,否则横/竖切一刀,这种划分方式的权值为两个子矩阵的复杂度的max。这个矩阵的复杂度为所有划分方式的权值中的最小值 + 1。n <= 185, 5s。

    解:考虑到复杂度不会超过2log,于是设fijkl为左边界为i,上下边界为jk,复杂度为l的矩形右边界最远能到的列。转移的时候有一个非常优秀的单调指针,不知道为什么......

      1 #include <bits/stdc++.h>
      2  
      3 const int N = 190;
      4  
      5 short G[N][N], a[N][N][N][18], b[N][N][N][18], sum1[N][N], sum2[N][N]; /// a->  b|
      6 char str[N];
      7  
      8 inline short get1(short l, short r, short i) { /// |
      9     return sum1[r][i] - sum1[l - 1][i];
     10 }
     11 inline short get2(short i, short l, short r) { /// -
     12     return sum2[i][r] - sum2[i][l - 1];
     13 }
     14  
     15 inline void exmax(short &a, const short &b) {
     16     a < b ? a = b : 0;
     17     return;
     18 }
     19 inline short Min(const short &a, const short &b) {
     20     return a > b ? b : a;
     21 }
     22  
     23 int main() {
     24  
     25  
     26     //printf("%d 
    ", (sizeof(a) * 2 + sizeof(G) + sizeof(str)) / 1048576);
     27     short n, m;
     28     scanf("%hd%hd", &n, &m);
     29     for(register short i(1); i <= n; ++i) {
     30         scanf("%s", str + 1);
     31         for(register short j(1); j <= m; ++j) {
     32             G[i][j] = (str[j] == '#');
     33             sum1[i][j] = sum1[i - 1][j] + G[i][j];
     34             sum2[i][j] = sum2[i][j - 1] + G[i][j];
     35             //printf("%hd %hd G = %hd 
    ", i, j, G[i][j]);
     36         }
     37     }
     38  
     39     for(register short l(1); l <= n; ++l) {
     40         for(register short r(l); r <= n; ++r) {
     41             short last = -1;
     42             for(register short i(m); i >= 1; --i) {
     43                 short tot(get1(l, r, i));
     44                 //printf("tot = %hd 
    ", tot);
     45                 if(tot != 0 && tot != r - l + 1) {
     46                     a[l][r][i][0] = i - 1;
     47                     last = -1;
     48                 }
     49                 else if(last != tot) {
     50                     a[l][r][i][0] = i;
     51                     last = tot;
     52                 }
     53                 else {
     54                     a[l][r][i][0] = a[l][r][i + 1][0];
     55                 }
     56                 //printf("a %hd %hd %hd 0 = %hd 
    ", l, r, i, a[l][r][i][0]);
     57             }
     58         }
     59     }
     60  
     61     /*for(short l = 1; l <= m; l++) {
     62         for(short r = l; r <= m; r++) {
     63             short last = -1;
     64             for(short i = n; i >= 1; i--) {
     65                 short tot = get2(i, l, r);
     66                 //printf("tot = %hd 
    ", tot);
     67                 if(tot != r - l + 1 && tot != 0) {
     68                     b[i][l][r][0] = i - 1;
     69                     last = -1;
     70                 }
     71                 else if(tot != last) {
     72                     b[i][l][r][0] = i;
     73                     last = tot;
     74                 }
     75                 else {
     76                     b[i][l][r][0] = b[i + 1][l][r][0];
     77                 }
     78                 //printf("b %hd %hd %hd 0 = %hd 
    ", i, l, r, b[i][l][r][0]);
     79             }
     80         }
     81     }*/
     82  
     83     if(a[1][n][1][0] == m) {
     84         printf("%hd
    ", 0);
     85         return 0;
     86     }
     87  
     88     for(register short j(1); j <= 17; ++j) {
     89  
     90         //printf("------------------- %hd -------------------- 
    ", j);
     91         for(register short i(m); i >= 1; --i) {
     92             for(register short l(1); l <= n; ++l) {
     93                 short p = l;
     94                 for(register short r(l); r <= n; ++r) {
     95                     exmax(a[l][r][i][j], a[l][r][i][j - 1]);
     96                     short t(a[l][r][i][j - 1]);
     97                     t = a[l][r][t + 1][j - 1];
     98                     exmax(a[l][r][i][j], t);
     99                     if(a[l][r][i][j] == m || l == r) continue;
    100  
    101                     for(; p < r; ++p) {
    102                         /// p [l, p] [p + 1, r]
    103                         t = Min(a[l][p][i][j - 1], a[p + 1][r][i][j - 1]);
    104                         // if(a[l][p][i][j - 1] <= a[l][r][i][j]) break;
    105                         if(a[l][p][i][j - 1] == i - 1) break;
    106                         if(p == r - 1 || Min(a[l][p + 1][i][j - 1], a[p + 2][r][i][j - 1]) < t) {
    107                             exmax(a[l][r][i][j], t);
    108                             break;
    109                         }
    110                     }
    111  
    112                 }
    113             }
    114             if(a[1][n][1][j] == m) {
    115                 printf("%hd
    ", j);
    116                 return 0;
    117             }
    118         }
    119  
    120         /*for(short l = 1; l <= n; l++) {
    121             for(short r = l; r <= n; r++) {
    122                 for(short i = 1; i <= m; i++) {
    123                     printf("a %hd %hd %hd = %hd 
    ", l, r, i, a[l][r][i][j]);
    124                 }
    125             }
    126         }
    127         printf("--------------- 
    ");
    128         for(short l = 1; l <= m; l++) {
    129             for(short r = l; r <= m; r++) {
    130                 for(int i = 1; i <= n; i++) {
    131                     printf("b %hd %hd %hd = %hd 
    ", i, l, r, b[i][l][r][j]);
    132                 }
    133             }
    134         }
    135         puts("");*/
    136     }
    137  
    138     /*for(register short i = 0; i <= 17; i++) {
    139         if(a[1][n][1][i] == m) {
    140             printf("%hd
    ", i);
    141             break;
    142         }
    143         if(b[1][1][m][i] == n) {
    144             printf("%hd
    ", i);
    145             break;
    146         }
    147     }*/
    148  
    149     return 0;
    150 }
    AC代码
  • 相关阅读:
    sizeof运算符:c
    c语言学习笔记重点理解 杂 给自己看
    代码编写永远记住一句话
    xcode DEBUG每个按钮的解释说明 ios
    Consecutive Subsequence CodeForces
    Cyclic Components CodeForces
    nyoj-0737-石子合并(dp)
    nyoj-0708-ones(dp)
    nyoj-0613-免费馅饼(dp)
    nyoj-0469-擅长排列的小明 II(找规律)
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10830406.html
Copyright © 2011-2022 走看看