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

解:BFS即可。

 #include <bits/stdc++.h>

 const int N = ;
const int dx[] = {, , -, };
const int dy[] = {, , , -}; struct Node {
int x, y;
Node(int X = , int Y = ) {
x = X;
y = Y;
}
}; int vis[N][N], d[N][N];
char str[N];
std::queue<Node> Q; int main() { int n, m, ans = ;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++) {
scanf("%s", str + );
for(int j = ; j <= m; j++) {
if(str[j] == '#') {
Q.push(Node(i, j));
vis[i][j] = ;
d[i][j] = ;
}
}
} while(Q.size()) {
int x = Q.front().x, y = Q.front().y;
Q.pop();
for(int i = ; i < ; i++) {
int tx = x + dx[i], ty = y + dy[i];
if(tx < || ty < || tx > n || ty > m || vis[tx][ty]) {
continue;
}
vis[tx][ty] = ;
d[tx][ty] = d[x][y] + ;
Q.push(Node(tx, ty));
ans = std::max(ans, d[tx][ty]);
}
}
printf("%d\n", ans);
return ;
}

AC代码

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

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

 #include <bits/stdc++.h>

 const int N = ;

 char str1[N], str2[N];
int n; int main() { int n1, n2, x1, x2;
scanf("%d%d%d", &n1, &n2, &n);
scanf("%d%d", &x1, &x2);
scanf("%s%s", str1 + , str2 + ); bool f = ;
int L = , R = n1 + ;
for(int i = n; i >= ; i--) { if(str2[i] == 'L' || str2[i] == 'R') { }
else if(str2[i] == 'D') {
L = std::max(L - , );
}
else {
R = std::min(R + , n1 + );
} if(str1[i] == 'L' || str1[i] == 'R') { }
else if(str1[i] == 'D') {
R = R - ;
}
else {
L = L + ;
}
if(L + >= R) {
f = ;
break;
} }
if(x1 <= L || R <= x1) {
f = ;
}
L = , R = n2 + ;
for(int i = n; i >= && f; i--) { if(str2[i] == 'U' || str2[i] == 'D') { }
else if(str2[i] == 'L') {
R = std::min(R + , n2 + );
}
else {
L = std::max(L - , );
} if(str1[i] == 'U' || str1[i] == 'D') { }
else if(str1[i] == 'L') {
L = L + ;
}
else {
R = R - ;
}
if(L + >= R) {
f = ;
break;
} }
if(x2 <= L || R <= x2) {
f = ;
}
if(f) {
printf("YES\n");
}
else {
printf("NO\n");
}
return ;
}

AC代码

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

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

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

 #include <bits/stdc++.h>

 const int N = ;

 struct Edge {
int nex, v;
}edge[N << ]; int tp; int n, e[N], sg[N], f[N], Ans; inline void add(int x, int y) {
edge[++tp].v = y;
edge[tp].nex = e[x];
e[x] = tp;
return;
} void DFS(int x, int fa) {
int a = , b = ;
for(int i = e[x]; i; i = edge[i].nex) {
int y = edge[i].v;
if(y == fa) continue;
DFS(y, x);
if(a < f[y] + ) {
b = a;
a = f[y] + ;
}
else {
b = std::max(b, f[y] + );
}
}
Ans = std::max(Ans, std::max(a + b - , a));
f[x] = a;
return;
} int main() { int n;
scanf("%d", &n);
for(int i = , x, y; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
} DFS(, ); /// cal Ans
sg[] = ;
sg[] = ;
for(int i = ; i <= Ans; i++) {
if(std::min(sg[i - ], sg[i - ]) == ) {
sg[i] = ;
}
else {
sg[i] = ;
}
} if(sg[Ans]) {
printf("First\n");
}
else {
printf("Second\n");
} return ;
}

AC代码

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

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

 #include <bits/stdc++.h>

 const int N = ;

 short G[N][N], a[N][N][N][], b[N][N][N][], sum1[N][N], sum2[N][N]; /// a->  b|
char str[N]; inline short get1(short l, short r, short i) { /// |
return sum1[r][i] - sum1[l - ][i];
}
inline short get2(short i, short l, short r) { /// -
return sum2[i][r] - sum2[i][l - ];
} inline void exmax(short &a, const short &b) {
a < b ? a = b : ;
return;
}
inline short Min(const short &a, const short &b) {
return a > b ? b : a;
} int main() { //printf("%d \n", (sizeof(a) * 2 + sizeof(G) + sizeof(str)) / 1048576);
short n, m;
scanf("%hd%hd", &n, &m);
for(register short i(); i <= n; ++i) {
scanf("%s", str + );
for(register short j(); j <= m; ++j) {
G[i][j] = (str[j] == '#');
sum1[i][j] = sum1[i - ][j] + G[i][j];
sum2[i][j] = sum2[i][j - ] + G[i][j];
//printf("%hd %hd G = %hd \n", i, j, G[i][j]);
}
} for(register short l(); l <= n; ++l) {
for(register short r(l); r <= n; ++r) {
short last = -;
for(register short i(m); i >= ; --i) {
short tot(get1(l, r, i));
//printf("tot = %hd \n", tot);
if(tot != && tot != r - l + ) {
a[l][r][i][] = i - ;
last = -;
}
else if(last != tot) {
a[l][r][i][] = i;
last = tot;
}
else {
a[l][r][i][] = a[l][r][i + ][];
}
//printf("a %hd %hd %hd 0 = %hd \n", l, r, i, a[l][r][i][0]);
}
}
} /*for(short l = 1; l <= m; l++) {
for(short r = l; r <= m; r++) {
short last = -1;
for(short i = n; i >= 1; i--) {
short tot = get2(i, l, r);
//printf("tot = %hd \n", tot);
if(tot != r - l + 1 && tot != 0) {
b[i][l][r][0] = i - 1;
last = -1;
}
else if(tot != last) {
b[i][l][r][0] = i;
last = tot;
}
else {
b[i][l][r][0] = b[i + 1][l][r][0];
}
//printf("b %hd %hd %hd 0 = %hd \n", i, l, r, b[i][l][r][0]);
}
}
}*/ if(a[][n][][] == m) {
printf("%hd\n", );
return ;
} for(register short j(); j <= ; ++j) { //printf("------------------- %hd -------------------- \n", j);
for(register short i(m); i >= ; --i) {
for(register short l(); l <= n; ++l) {
short p = l;
for(register short r(l); r <= n; ++r) {
exmax(a[l][r][i][j], a[l][r][i][j - ]);
short t(a[l][r][i][j - ]);
t = a[l][r][t + ][j - ];
exmax(a[l][r][i][j], t);
if(a[l][r][i][j] == m || l == r) continue; for(; p < r; ++p) {
/// p [l, p] [p + 1, r]
t = Min(a[l][p][i][j - ], a[p + ][r][i][j - ]);
// if(a[l][p][i][j - 1] <= a[l][r][i][j]) break;
if(a[l][p][i][j - ] == i - ) break;
if(p == r - || Min(a[l][p + ][i][j - ], a[p + ][r][i][j - ]) < t) {
exmax(a[l][r][i][j], t);
break;
}
} }
}
if(a[][n][][j] == m) {
printf("%hd\n", j);
return ;
}
} /*for(short l = 1; l <= n; l++) {
for(short r = l; r <= n; r++) {
for(short i = 1; i <= m; i++) {
printf("a %hd %hd %hd = %hd \n", l, r, i, a[l][r][i][j]);
}
}
}
printf("--------------- \n");
for(short l = 1; l <= m; l++) {
for(short r = l; r <= m; r++) {
for(int i = 1; i <= n; i++) {
printf("b %hd %hd %hd = %hd \n", i, l, r, b[i][l][r][j]);
}
}
}
puts("");*/
} /*for(register short i = 0; i <= 17; i++) {
if(a[1][n][1][i] == m) {
printf("%hd\n", i);
break;
}
if(b[1][1][m][i] == n) {
printf("%hd\n", i);
break;
}
}*/ return ;
}

AC代码

agc033的更多相关文章

  1. 【AtCoder】AGC033(A-F)

    AGC033 A - Darker and Darker 直接BFS #include <bits/stdc++.h> #define fi first #define se second ...

  2. AGC033 D~F——[ 值放到角标的DP ][ 思路+DP ][ 思路 ]

    地址:https://atcoder.jp/contests/agc033/ D Complexity dp[ i ][ j ][ k ][ l ] 表示左上角是 ( i , j ) .右下角是 ( ...

  3. AtCoder整理(持续更新中……)

    做了那么久的atcoder觉得自己的题解发的很乱 给有想和我一起交流atcoder题目(或者指出我做法的很菜)(或者指责我为什么整场比赛只会抄题解)的同学一个索引的机会??? 于是写了个爬虫爬了下 A ...

随机推荐

  1. 自动生成DTO(Sugar框架)

    step1:启动api项目 step2:使用postman工具,填上接口地址http://localhost:7788/api/automapper/AutoMapperSuper step3:表格数 ...

  2. 如何为ABAP程序添加权限检查

    一.确认权限对象,及其关联字段: TCode: SU21 例如权限对象"M_MSEG_WMB",它关联字段为"WERKS",详见下图: 二.在ABAP代码中添加 ...

  3. netty 私有协议栈

    通信协议从广义上区分,可以分为公有协议和私有协议.由于私有协议的灵活性,它往往会在某个公司或者组织内部使用,按需定制,也因为如此,升级起来会非常方便,灵活性好.绝大多数的私有协议传输层都基于TCP/I ...

  4. NuGet 命令行使用EntityFrameWork

    初始化 Enable-migrations 迁移 Add-Migration Donator_Add_CreationTime 执行操作 UpDate-database 撤销更改 Update-Dat ...

  5. WPF 多语言

    1.http://www.cnblogs.com/bear831204/archive/2009/03/17/1414026.html 2.http://www.cnblogs.com/horan/a ...

  6. robocopy——Windows下的高效文件拷贝

    1. 基本用法 C:\Users\>RoboCopy /? ------------------------------------------------------------------- ...

  7. python学习笔记4_数据清洗与准备

    一.处理缺失值 pandas使用浮点值NaN(Not a Number)来显示缺失值,并将缺失值称为NA(not available(不可用)). NA常用处理方法: dropna:根据每个标签的值是 ...

  8. sqlserver2005分页存储过程

    Create proc [dbo].[sp_AbiTableLoad] ---------------------------------------------- -- 单表多表分页存储过程 -- ...

  9. JSON对象获取指定元素以及JSON.parse() 与 JSON.stringify() 的区别

    利用 JSON.parse(param) 实现 例: var param = { "name" : "张三", "text" : { &qu ...

  10. hadoop2.x 完全分布式详细集群搭建(图文:4台机器)

    在准备之前说一下本次搭建的各节点角色,进程. nameNode 进程:NameNode dataNode  进程:DataNode resourceManager :ResourceManager n ...