/************************************************************************/
/* 题目的意思是说有一个高度为n的楼,每个楼层都有一个方向,共4个方向,你可以每次跳的最大高度为
/* h,并且只有两个楼层间的方向是一样的时候才可以跳。只要你能跳到 【n-h+1,n】层都算是一种成功
/* 的方法,那么问你楼层方向的排法有几种。一开始你位于楼0,你可以跳到【1,h】的任意楼层开始。
比如 你的排法是123123 那么h=3的时候,可以成功,但是h=2 则不行。比较难以解释的题目
我们可以设dp[cur_lever][x][y][z][w][isxok][isyok][iszok][iswok]
表示当前在楼层cur_lever 并且方向1相距现在楼层的高度差为x,方向2为y。类推
而isxok表示这个时候我通过方向1时候可以,跳,1表示我可以接着用沿着方向1跳到满足要求的地方 0 表示
现在你即使在这个楼层放了方向1的设计也是不可以跳到的。现在如果x>=h这个时候在curlver放了方向1,
isxok 必定会由 1-》0 or 0-》0那么这个维度其实是可以省略的,只要我们保留高度差就行了,对于isxok
为了统统保留成高度 差为h,即使事实上高度差为1 or 2 or<h的任意值,就可以简化wei
dp[cur_lever][x][y][z][w]
/************************************************************************/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
long long dp[2][32][32][32][32];
long long const MOD = 1000000009L;
int main(){
int n,h;
while(cin>>n>>h){
int now,pre;
dp[0][0][0][0][0]=1;
long long ans = 0;
for(int i=1;i<=n;i++){
now = i&1;
pre = 1-now;
for(int x1=0;x1<=h;x1++)
for(int x2=0;x2<=h;x2++)
for(int x3=0;x3<=h;x3++)
for(int x4=0;x4<=h;x4++){
long long t = dp[pre][x1][x2][x3][x4];
if(t==0) continue;
t%=MOD;
int nx1 = min(h,x1+1);
int nx2 = min(h,x2+1);
int nx3 = min(h,x3+1);
int nx4 = min(h,x4+1);
//put on direct x1
if(x1==h) dp[now][h][nx2][nx3][nx4]+=t;
else dp[now][0][nx2][nx3][nx4]+=t;
if(x2==h) dp[now][nx1][h][nx3][nx4]+=t;
else dp[now][nx1][0][nx3][nx4]+=t;
if(x3==h) dp[now][nx1][nx2][h][nx4]+=t;
else dp[now][nx1][nx2][0][nx4]+=t;
if(x4==h) dp[now][nx1][nx2][nx3][h]+=t;
else dp[now][nx1][nx2][nx3][0]+=t;
dp[pre][x1][x2][x3][x4] = 0;
}
}
for(int x1=0;x1<=h;x1++){
for(int x2=0;x2<=h;x2++){
for(int x3=0;x3<=h;x3++){
for(int x4=0;x4<=h;x4++){
if(x1<h||x2<h||x3<h||x4<h){
ans+=dp[now][x1][x2][x3][x4];
ans%=MOD;
}
dp[now][x1][x2][x3][x4] = 0;
//
}
}
}
}
cout<<ans<<endl;
}
}
这个是超时了,h^4*n 考虑到其实这里有
codeforces 268D
最新推荐文章于 2019-08-25 13:56:43 发布