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\n", 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\n");
80     }
81     else {
82         printf("NO\n");
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\n");
63     }
64     else {
65         printf("Second\n");
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 \n", (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 \n", 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 \n", 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 \n", 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 \n", 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 \n", i, l, r, b[i][l][r][0]);
 79             }
 80         }
 81     }*/
 82  
 83     if(a[1][n][1][0] == m) {
 84         printf("%hd\n", 0);
 85         return 0;
 86     }
 87  
 88     for(register short j(1); j <= 17; ++j) {
 89  
 90         //printf("------------------- %hd -------------------- \n", 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\n", 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 \n", l, r, i, a[l][r][i][j]);
124                 }
125             }
126         }
127         printf("--------------- \n");
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 \n", 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\n", i);
141             break;
142         }
143         if(b[1][1][m][i] == n) {
144             printf("%hd\n", i);
145             break;
146         }
147     }*/
148  
149     return 0;
150 }
AC代码

 

转载于:https://www.cnblogs.com/huyufeifei/p/10830406.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值