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. C# 串口编程 对端口的访问被拒绝

    感谢Sunny秋刀鱼.https://www.cnblogs.com/527289276qq/p/5595798.html 在页面或者窗口Unloaded事件中关闭串口即可.

  2. sparkStreaming结合sparkSql进行日志分析

    package testimport java.util.Propertiesimport org.apache.spark.SparkConfimport org.apache.spark.Spar ...

  3. tomcat下面部署多个项目

    最近需要部署多个项目,我目前所知道的两种方法,第一种是一个tomcat部署一个项目,需要布置多个tomcat就可以部署多个项目.第二种就是一个tomcat下面部署多个项目. 首先我们先来说说两种的优劣 ...

  4. 在 my_rootfs 中建立 Linux 目录树

    [arm@localhost my_rootfs]#mkdir bin dev etc home lib mnt proc sbin sys tmp root usr [arm@localhost m ...

  5. [转]NuGet学习笔记(1) 初识NuGet及快速安装使用

    关于NuGet园子里已经有不少介绍及使用经验,本文仅作为自己研究学习NuGet一个记录. 初次认识NuGet是在去年把项目升级为MVC3的时候,当时看到工具菜单多一项Library Package M ...

  6. 解决element 分页组件,搜索过后current-page 绑定的数据变了,但是页面当前页码并没有变的问题

    前言上一篇写前台解决分页问题的时候没有这个问题,但是在实际项目后台中有遇到过,所以在这里专门说一下,如果参考前台分页出现这种问题了,也可以使用这种方法!bug:vue和element实现的后台分页,当 ...

  7. Python基础笔记_变量类型

     下面是W3C学习笔记 , , ) :] ]) :]) :]) :-]) :-]) ]) :]) :]) ) , , ]) :]) :]) ) , , , ]) :]) :]) ) ] = , ])) ...

  8. 模拟+贪心——cf1131E

    超级恶心的题,写了好久,直接倒序模拟做,但是网上有博客好像是直接正序dp做的.. 因为左端点和右端点是永远不会变的,然后情况要考虑全 /* 从后往前插 只要记录左连续,右连续,中间连续 左端点一定是L ...

  9. 自己编写jquery插件

    http://blog.csdn.net/chenxi1025/article/details/52222327 https://www.cnblogs.com/ajianbeyourself/p/5 ...

  10. Java-slf4j:sfl4j

    ylbtech-Java-slf4j:sfl4j 1.返回顶部 1. SLF4J,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种 ...