蓝桥杯 算法提高VIP 摆花 dp 记忆搜索 2种做法

版权声明:点个关注(^-^)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]);
	}


}

猜你喜欢

转载自blog.csdn.net/weixin_41793113/article/details/88535411