题目描述:
不过 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]);
}
}