题目描述:
不过 uim 由于买了一些书,口袋里只剩 𝑀M 元 (𝑀≤10000)(M≤10000)。
餐馆虽低端,但是菜品种类不少,有 𝑁N 种 (𝑁≤100)(N≤100),第 𝑖i 种卖 𝑎𝑖ai 元 (𝑎𝑖≤1000)(ai≤1000)。由于是很低端的餐馆,所以每种菜只有一份。
小 A 奉行“不把钱吃光不罢休”,所以他点单一定刚好把 uim 身上所有钱花完。他想知道有多少种点菜方法。
由于小 A 肚子太饿,所以最多只能等待 11 秒。
解题思路:
dp[i - 1][ j ]就代表了:选前i-1道菜,而且还正好花了j元钱,也代表了我们不买第i道菜所需要的方案数量
dp[i - 1][j - a[ i ]]:选前i-1道菜,而且还正好花了j-a[ i ]元钱。当我们买了前i道菜花了j元钱时,我们减去这第i道菜然后减去买第i道菜花的钱,得到的方案数是不变的,也就是说dp[i - 1][j - a[ i ]]就代表了买第i道菜的方案数量,这一思想在背包问题中也有所体现。
代码:
package lanqiao;import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int N = sc.nextInt(); //菜的种类int M = sc.nextInt(); //钱int[] a = new int[N + 1];int[][] dp = new int[M + 1][M + 1];for(int i = 1;i <= N;i ++){a[i] = sc.nextInt();}for(int i = 1;i <= N;i ++){for(int j = 1;j <= M;j ++){if(j == a[i]){dp[i][j] = dp[i - 1][j] + 1; //多加一个菜}if(j > a[i]){dp[i][j] = dp[i - 1][j] + dp[i - 1][j - a[i]]; //不买这道菜+买这道菜}if(j < a[i]){dp[i][j] = dp[i - 1][j]; //钱不够,未加菜}}}System.out.println(dp[N][M]);}
}