(sol)
状态
[f_{i, dis_1, dis_2, dis_3, dis_4}
]
表示到了第 (i) 层,其中 (dis_{1}) 表示第一根柱子剩下的最靠上的横木到当前 (i) 层的距离,以此类推。
显然后四维的范围 ([0, h])
枚举这一层所留下的横木是在哪一个梯子上,对应的 (dis) 变为 (0), 如果 (dis) 为 (h),说明已经断了,这种情况还是 (h), 其他的 (dis + 1) 如果已经是 (h) 则不变
时间复杂度 (O(nh^4))
由于每一层必定会存在一个横木,也就是必定会有一个梯子 (dis) 为 (0)
所以了以减少以为的 (dis)
同时改为 (0/1) 记录这一个梯子是否能不断连接到当前行。
[f_{i, 0/1, dis_{2}, dis_{3}, dis_{4}}
]
表示到了 (i) 层,在这一层放横木的那个梯子是否能爬到当前层,(dis) 同理
时间复杂度 (O(nh^3))
滚动数组优化空间
(cod)
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int mod = 1e9 + 9;
int n, h;
int now, old;
int f[2][2][33][33][33];
#define nex(x) ((x) == h ? h :(x) + 1)
void MOD(int &x) {
if (x >= mod) x -= mod;
}
int main() {
scanf("%d%d", &n, &h);
old = 0, now = 1;
f[old][1][0][0][0] = 1;
int tmp;
for (int i = 1; i <= n; i ++) {
for (int j = 0; j <= 1; j ++)
for (int x = 0; x <= h; x ++)
for (int y = 0; y <= h; y ++)
for (int z = 0; z <= h; z ++)
if (tmp = f[old][j][x][y][z]) {
MOD(f[now][j][nex(x)][nex(y)][nex(z)] += tmp);
MOD(f[now][x < h][nex(y)][nex(z)][j == 1 ? 1 : h] += tmp);
MOD(f[now][y < h][nex(x)][nex(z)][j == 1 ? 1 : h] += tmp);
MOD(f[now][z < h][nex(x)][nex(y)][j == 1 ? 1 : h] += tmp);
f[old][j][x][y][z] = 0;
}
swap(now, old);
}
int ans = 0;
for (int j = 0; j <= 1; j ++)
for (int x = 0; x <= h; x ++)
for (int y = 0; y <= h; y ++)
for (int z = 0; z <= h; z ++)
if (j == 1 || x < h || y < h || z < h)
ans += f[old][j][x][y][z], MOD(ans);
printf("%d", ans);
return 0;
}