XTU OJ 1378 Blocks

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列,那么合法的安排方案为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

思路分析:主要就是递推和递归,出口的设置就是一般都是找最特殊的地方,最开头的部分,普遍数据都是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);
	}	
}

猜你喜欢

转载自blog.csdn.net/qq_24917263/article/details/127653823