题目:
题目描述
有K 种不同规则的长方体砖块,长宽高分别是:1×1×1、2×1×1、3×1×1…,K× 1×1.还给出一个W×1×1 的地基,如下图所示,W=9, k=3,下面的是地基:
Luogu
现在你要在地基上堆放砖块,必须满足如下的规则:
1、 砖块只能横放,不能竖放。 2、 砖块必须放置在整数位置,且不能越出地基。 3、 砖块任何部分的正下方都必须要有其他砖块或者是地基。 例如:下图是不合法的放置方式,有 4 个不合法的地方:
Luogu
我们定义一种堆放砖块方案的高度 height:它是指该方案中最高的砖块是第几层, 其中地基是第0 层,例如(图二)的高度是 3。 我们定义不同的堆放方案:例如有两种堆放方案 A 和B,只要满足两个条件之一, 方案A 和方案 B 就是不同的方案: 1、 在某个位置方案 A 有砖块而方案 B 在该位置没有砖块,或者方案 B 有砖块 而方案A 没有。 2、 在某个位置方案 A 和方案B 都有砖块,但是它们不是同一种规格的砖块。
给定地基的长度W,和地砖的最大长度 K,你的任务是计算有多少种不同的堆放 砖块的方案,你的堆放砖块方案的高度 height 不能超过给定的H。答案模 1000 000007。
例如:下图是W=3, k=3, H=2 的所有合法方案:
输入输出格式
输入格式:
输出格式:
共G 行,每行一个整数。
输入输出样例
输入样例#1:
3
3 1 3
3 2 3
10 10 3
输出样例#1:
13
83
288535435
说明
第一行,一个整数 G,表示有 G 组测试数据。1 <= G <=3。 每组测试数据格式如下:
一行,三个整数W、H、K 。1 <= W, H <= 50。 1 <= K <= W
思路:
dp。
f[i][j]表示长j高i的方案数。
代码:
#include<bits/stdc++.h>
using namespace std;
#define md 1000000007
#define maxn 50
#define read(x) scanf("%d",&x)
int n,m,h;
long long f[maxn+5][maxn+5];
long long g[maxn+5];
int main() {
int T;
read(T);
while(T--) {
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
read(n),read(h),read(m);
g[0]=1;
for(int i=1;i<=n;i++)
for(int j=(i-m>0?i-m:0);j<i;j++) {
g[i]=(g[i]+g[j])%md;
}
for(int i=1;i<=h;i++) f[i][0]=1;
for(int i=1;i<=n;i++) f[0][i]=1;
for(int i=1;i<=h;i++) {
for(int j=1;j<=n;j++) {
f[i][j]=f[i][j-1];
for(int k=1;k<=j;k++) {
f[i][j]=(f[i][j]+((f[i-1][k]*(long long)g[k])%md*(long long)f[i][j-k-1>0?j-k-1:0])%md)%md;
}
}
}
printf("%lld\n",f[h][n]);
}
return 0;
}