Blocks |
||
[ Submit Code ] [ Top 20 Runs ] [ Runs Status ] | ||
Acceteped : 644 | Submit : 924 | |
Time Limit : 1000 MS | Memory Limit : 65536 KB | |
Description |
||
Blocks题目描述给你一个n块积木,每个积木块都是立方体,现在把它们排列一排,成m列,要求每列上至少有1个积木,且从左到右,每列的积木数量呈严格单调下降。比如8块积木,排成3列,那么合法的安排方案为 输入第一行是一个整数T(1≤T≤1000),表示样例的个数。 以后每个样例占一行,为两个整数 n(1≤n≤100),m(1≤m≤10)。 输出依次每行输出一个样例的结果,为一个整数。 样例输入2 8 3 13 4 样例输出2 3 样例解释第二个样例的合法方案为 |
思路分析:主要就是递推和递归,出口的设置就是一般都是找最特殊的地方,最开头的部分,普遍数据都是1或者0
#include <stdio.h>
#include <string.h>
__int64 a[101][11][110] = {0};
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d %d",&n,&m);
memset(a,0,sizeof(a));
a[1][1][1] = 1;
for(int i = 2;i<=n;i++){//a[i][j][k]共i块积木,排成j列,第一列为k块积木
for(int j = 1;j<=m;j++){//排成m列
for(int k = 1;k<=i;k++){
if(i==k&&j==1){
a[i][j][k] = 1;//如果说第一列的积木总数为全体积木总数,且j==1
//即只有一列的时候,情况只有一种
//递推
}
else{
for(int u = k-1;u>=1;u--){
a[i][j][k] +=a[i-k][j-1][u];//递归
//我们要求i块积木,排成j列,第一列为k块积木的情况数,我们就需要知道减去第一列积木,得到上一种情况数
//换句话说对于数字36,如果我们排列好了,那么记为(36),如果说,在第一列加上9,那么就知道了(45)
//对于某种情况,对于(37)加上8同样也知道了(45)
//因此对于(45),我们就去找(44),(43)...(36),将这几种加起来就得到了(45)
//然后一切的开头就只有,1,1,1和i,j,i两种情况都是1
}
}
}
}
}
int cnt = 0;
for(int i = 1;i<=n;i++){
cnt+= a[n][m][i];//n块积木,排成m列的情况总数为,第一列分别为1,2,3....n块积木的情况总数之和
}
printf("%d\n",cnt);
}
}