96 摆花
作者: Turbo时间限制: 1S章节: 动态规划
问题描述 :
小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。
样例输入
2 4
3 2
样例输出
2
输入输出样例说明
有2种摆花的方案,分别是(1,1,1,2), (1,1,2,2)。括号里的1和2表示两种花,比如第一个方案是前三个位置摆第一种花,第四个位置摆第二种花。
输入说明 :
第一行包含两个正整数n和m,中间用一个空格隔开。
第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。
0<n≤100,0<m≤100,0≤ ai≤100。
输出说明 :
输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对1000007取模的结果。
输入范例 :
3 5
3 4 4
输出范例 :
16
递归版代码:
/*
T96 摆花
算法概述:设f[i][j]表示用i种花摆成j盆的方案数量
f[i][j]可以分成两种情况:
第一,摆上第i种花,此时方案数量为:f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][j-a[i]]
或者f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][1],具体受第i种花的数量和摆花的总数量限制
第二,不摆第i种花,此时方案数量为:f[i-1][j]
由此得出状态转移方程:
f[i][j] = f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][j-a[i]] + f[i-1][j]
*/
#include<stdio.h>
#define MAX_SIZE 105
int a[MAX_SIZE];
int calSchAmt(int n, int m);// calSchAmt(i, j)就是f[i][j]
int main() {
int i = 0;
int n = 3, m = 5;
scanf("%d%d", &n, &m);
a[1] = 3;
a[2] = 4;
a[3] = 4;
for (i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("%d\n", calSchAmt(n, m));
return 0;
}
// 将n种花摆成m盆的方案数量
int calSchAmt(int n, int m) {
int i = 0;
int temp = 0;
int count = 0;
if (n == 1) {// 递归出口
if (a[n] >= m)// 花够
return 1;
else// 花不够
return 0;
}
if (m == 1) {
//printf("++++f(%d, %d)=%d\n", n, m, n);
return n;
}
if (m == 0) {
return 0;
}
for (i = 1; i <= a[n]; i++) {
if (m - i >= 0) {
temp = calSchAmt(n - 1, m - i) % 1000007;
//printf("f(%d, %d)=%d ", n - 1, m - i, temp);
count += temp;
}
}
temp = calSchAmt(n - 1, m) % 1000007;
//printf("f(%d, %d)=%d\n", n - 1, m, temp);
count += temp;
count %= 1000007;
return count;
}
非递归版代码:
/*
T96 摆花
算法概述:设f[i][j]表示用i种花摆成j盆的方案数量
f[i][j]可以分成两种情况:
第一,摆上第i种花,此时方案数量为:f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][j-a[i]]
或者f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][1],具体受第i种花的数量和摆花的总数量限制
第二,不摆第i种花,此时方案数量为:f[i-1][j]
由此得出状态转移方程:
f[i][j] = f[i-1][j-1]+f[i-1][j-2]+……+f[i-1][j-a[i]] + f[i-1][j]
*/
#include<stdio.h>
#define MAX_SIZE 105
int a[MAX_SIZE];
int f[MAX_SIZE][MAX_SIZE];
int calSchAmt(int n, int m);
int main() {
int i = 0;
int n = 3, m = 5;
scanf("%d%d", &n, &m);
// a[1] = 3;
// a[2] = 4;
// a[3] = 4;
for (i = 1; i <= n; i++)
scanf("%d", &a[i]);
printf("%d\n", calSchAmt(n, m));
return 0;
}
// 将n种花摆成m盆的方案数量
int calSchAmt(int n, int m) {
int i = 0, j = 0, k = 0;
for (i = 1; i <= n; i++) {// 初始化
f[i][1] = 0;
for (j = 1; j <= i; j++)// i种花摆成一盆
if (a[j] > 0)
f[i][1] += 1;
for (j = 1; j <= m; j++)// 第一种花摆成j盆
f[1][j] = (a[1] >= j) ? 1 : 0;
}
for (i = 2; i <= n; i++) {
for (j = 2; j <= m; j++) {
for (k = 0; k <= a[i]; k++) {// 考虑第i种花(可以不摆)
if (j - k > 0)
f[i][j] += (f[i - 1][j - k] % 1000007);
if (j - k == 0) {// 只摆了第i种花
f[i][j] += 1;
break;
}
}
f[i][j] %= 1000007;
}
}
return f[n][m];
}