专栏文章
题解:AT_agc045_c [AGC045C] Range Set
AT_agc045_c题解参与者 22已保存评论 24
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 24 条
- 当前快照
- 2 份
- 快照标识符
- @mkkzvw37
- 此快照首次捕获于
- 2026/01/19 18:00 上个月
- 此快照最后确认于
- 2026/01/19 18:00 上个月
要去想怎么判断一个字符串能不能涂出来,可以贪心判断,有三个变量 ,初始 ,然后每次如果:
- 字符是
0- 如果 ,或者 ,那么
p--,q--; - 否则,
p--,然后q=B-1。
- 如果 ,或者 ,那么
- 字符是
1同理。 - 如果 ,
p=0;如果 ,q=0。 - 把 改成现在的字符。
枚举的暴力代码如下:
CPPint answer = 0;
for (int S = 0; S < 1 << n; S ++) {
int x = 0, p = A, q = B;
for (int i = 1; i <= n; i ++) {
int v = (S >> (i - 1) & 1);
if (v) {
if (x || !p) p = max(p - 1, 0), q = max(q - 1, 0);
else p = max(p - 1, 0), q = B - 1;
} else {
if (!x || !q) p = max(p - 1, 0), q = max(q - 1, 0);
else q = max(q - 1, 0), p = A - 1;
}
x = v;
}
if (!p && !q) {
answer ++;
}
}
然后就可以把 全部用动态规划的状态记录(第一维 ,第二维 ,第三维 ),用一个滚动数组,
CPPdp1 是当前的,dp2 是下一个。转移方程式非常简单的,这都不知道可以不做这题了。有下面的代码:for (int i = 1; i <= n; i ++) {
dp2[0][0][0] += dp1[0][0][0] + dp1[0][0][1];
dp2[0][0][1] += dp1[0][0][0] + dp1[0][0][1];
for (int x = 1; x <= A; x ++) {
dp2[x - 1][0][0] += dp1[x][0][0];
dp2[x - 1][0][1] += dp1[x][0][1];
dp2[x - 1][B - 1][1] += dp1[x][0][0];
dp2[x - 1][0][0] += dp1[x][0][1];
}
for (int y = 1; y <= B; y ++) {
dp2[0][y - 1][0] += dp1[0][y][0];
dp2[0][y - 1][1] += dp1[0][y][1];
dp2[0][y - 1][1] += dp1[0][y][0];
dp2[A - 1][y - 1][0] += dp1[0][y][1];
}
for (int x = 1; x <= A; x ++) for (int y = 1; y <= B; y ++) {
dp2[x - 1][y - 1][0] += dp1[x][y][0];
dp2[x - 1][y - 1][1] += dp1[x][y][1];
dp2[x - 1][B - 1][1] += dp1[x][y][0];
dp2[A - 1][y - 1][0] += dp1[x][y][1];
}
for (int x = 0; x <= A; x ++) for (int y = 0; y <= B; y ++) {
dp1[x][y][0] = dp2[x][y][0], dp1[x][y][1] = dp2[x][y][1];
dp2[x][y][0] = dp2[x][y][1] = 0;
}
}
这样的时间复杂度是 。
要维护矩阵每次向左下角移动,维护每行每列的和就可以了。优化之后时间复杂度变成 。
相关推荐
评论
共 24 条评论,欢迎与作者交流。
正在加载评论...