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# 反射的委托创建器

    原文:C# 反射的委托创建器 .Net 的反射是个很好很强大的东西,不过它的效率却实在是不给力.已经有很多人针对这个问题讨论过了,包括各种各样的 DynamicMethod 和各种各样的效率测试,不过 ...

  2. Python学习之文件操作(二)

    CSV文件处理 在Python中处理CSV文件可以使用模块csv.有关csv模块的官方资料看这里. 1 读取csv文件 csv.reader(csvfile, dialect='excel', **f ...

  3. Aria2配置文件-aria2.conf

    ##此部分主要分为几部分###1.文件保存#2.下载链接#3.进度保存#4.RPC相关#5.BT\PT下载相关 ##===================================#### 文件 ...

  4. h5页面在不同ios设备上的问题总结

    1.日期问题 对于yyyy-mm-dd hh:mm:ss 这种格式在ios系统不识别 时间格式化的时候,在浏览器端处理好好的,到了手机端,就变成NAN,或者null,这种情况,是ios系统不能转化这种 ...

  5. loj6247 九个太阳

    题意: k<=2^20,n<=10^15. 标程: #include<cstdio> using namespace std; typedef long long ll; ; ...

  6. Mysql 数据库crash恢复

    之前搭建的ghost博客比较坑,修改comment之后重启数据丢了,对node不熟悉,所以就切换回到wordpress了. 回滚快照之后发现数据库crash了,提示如下信息 2016-06-15 23 ...

  7. python requests 高级用法

    高级用法 本篇文档涵盖了 Requests 的一些高级特性. 会话对象 会话对象让你能够跨请求保持某些参数.它也会在同一个 Session 实例发出的所有请求之间保持 cookie, 期间使用 url ...

  8. W: 仓库 “http://ppa.launchpad.net/levi-armstrong/qt-libraries-trusty/ubuntu xenial Release” 没有 Release 文件。

    解决办法:将对应的PPA删除掉即可 使用以下命令切换到对应PPA目录: cd /etc/apt/sources.list.dsudo rm levi-armstrong-ubuntu-qt-libra ...

  9. 出错提示:“Could not flush the DNS Resolver Cache: 执行期间,函数出了问题”的解决方法

    在DNS解析中,出错提示:"Could not flush the DNS Resolver Cache: 执行期间,函数出了问题"的解决方法  . 由于公司网站空间更换了服务商. ...

  10. elasticDump的安装使用

    官方地址:官方地址:https://github.com/taskrabbit/elasticsearch-dump 安装方式如下:安装NodeJS下载源码:wget http://nodejs.or ...