版权声明:点个关注(^-^)V https://blog.csdn.net/weixin_41793113/article/details/88535411
题目描述
小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共m盆。通过调查顾客的喜好,小明列出了顾客最喜欢的n种花,从1到n标号。为了在门口展出更多种花,规定第i种花不能超过ai盆,摆花时同一种花放在一起,且不同种类的花需按标号的从小到大的顺序依次摆列。
试编程计算,一共有多少种不同的摆花方案。
样例说明
有2种摆花的方案,分别是(1,1,1,2), (1,1,2,2)。括号里的1和2表示两种花,比如第一个方案是前三个位置摆第一种花,第四个位置摆第二种花。
数据规模和约定
对于100%数据,有0< n≤100,0< m≤100,0≤ ai≤100。
输入
第一行包含两个正整数n和m,中间用一个空格隔开。
第二行有n个整数,每两个整数之间用一个空格隔开,依次表示a1、a2、……an。
输出
输出只有一行,一个整数,表示有多少种方案。注意:因为方案数可能很多,请输出方案数对1000007取模的结果。
样例输入
2 4 3 2
样例输出
2
先放个3维暴力递归+模拟,剪掉负数的情况,记忆搜索优化的代码org
import java.util.Scanner;
public class 摆花_记忆搜索 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
memo = new int[n+5][m+5][m+5];
a = new int[n+5];
for(int i=1;i<=n;i++)
a[i] = in.nextInt();
System.out.println(f(n,m,0));
}
static int[] a;
static int[][][] memo;
static int f(int n,int m,int k) {
if(n<0)
return 0;
if(memo[n][m][k]!=0)
return memo[n][m][k];
if(k>a[n])
return 0;
if(m==0)
return 1;
memo[n][m][k] = (f(n,m-1,k+1) + f(n-1,m,0))%1000007;
return memo[n][m][k];
}
}
下面这个的思想就和dp很接近了,递归思路,把当前第n种花,在不超过质量m的情况下,取0,1,2,3,...,a[n],把所有情况的答案累加起来
import java.util.Scanner;
public class 摆花_记忆搜索2 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
memo = new int[n+5][m+5];
a = new int[n+5];
for(int i=1;i<=n;i++)
a[i] = in.nextInt();
System.out.println(f(n,m));
}
static int[] a;
static int[][] memo;
static int f(int n,int m) {
if(memo[n][m]!=0)//可以初始化-1,防止记忆退化,100的数据规模就没必要了
return memo[n][m];
if(n==0)
return m==0?1:0;
for(int i=0;i<=Math.min(m, a[n]);i++)//递归思路,把当前第n种花,在不超过质量m的情况下,取0,1,2,3,...,a[n],把所有情况的答案累加起来
memo[n][m] = (memo[n][m] + f(n-1,m-i))%1000007;
return memo[n][m];
}
}
dp做法,一直感觉这种是背包问题,hhh,有误区,这里说下,背包是每取一个都有价值,这个是取到满质量了记为一种情况,所以还是有本质区别的,意思是只有出口有值为1~
import java.util.Scanner;
public class 摆花_dp {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
int[][] dp = new int[n+5][m+5];
int[] a = new int[n+5];
for(int i=1;i<=n;i++)
a[i] = in.nextInt();
dp[0][0] = 1;
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=0;k<=Math.min(j,a[i]);k++)
dp[i][j] = (dp[i][j] + dp[i-1][j-k])%1000007;
System.out.println(dp[n][m]);
}
}