题目描述
给你一个n块积木,每个积木块都是立方体,现在把它们排列一排,成m列,要求每列上至少有1个积木,且从左到右,每列的积木数量呈严格单调下降。比如8块积木,排成3列,那么合法的安排方案为521
或者431
。请问n块积木按规则排成m有多少种不同的方案?
输入
第一行是一个整数T(1≤T≤1000),表示样例的个数。
以后每个样例占一行,为两个整数 n(1≤n≤100),m(1≤m≤10)。
输出
依次每行输出一个样例的结果,为一个整数。
样例输入
2 8 3 13 4
样例输出
2 3
样例解释
第二个样例的合法方案为7321
,6421
,5431。
思路:我认为这是一个动态规划问题,设dp[i][j][k]表示的意义为i块积木按规则排成j列的第一列个数为k的方案,因此所求即为dp[n][m][1]+dp[n][m][2].......+dp[n][m][n],动态规划方程为;dp[i][j][k]=dp[i-k][j-1][0]..........+dp[i-k][j-1][k-1](这里k明显是能优化的,但是我没有,毕竟这样好理解,因为题目要单调递减,把小于k的全加起来就行了,但是有可能k有时候会比i-k要大,所以第k数组要开得跟i差不多大)。
AC代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int k;
scanf("%d",&k);
while(k--)
{
int dp[110][20][200];
memset(dp,0,sizeof(dp));
dp[1][1][1]=1;
int i,j,k,q,n,m,count=0;
scanf("%d%d",&n,&m);
for(i=2;i<=n;i++)
{
for(j=1;j<=m;j++)
{
for(k=1;k<=i;k++)
{
if(i==k&&j==1)//如果排成一列,那么开头必然就是总的个数,此时只有一种。
{
dp[i][j][k]=1;
}
else
{
for(q=k-1;q>=1;q--)
{
dp[i][j][k]+=dp[i-k][j-1][q];
}
}
}
}
}
for(i=1;i<=n;i++)
{
count+=dp[n][m][i];
}
printf("%d\n",count);
}
return 0;
}
代码可以优化一下,但是作者懒........(爬)......