P1164 小A点菜【java】【AC代码】

题目背景

uim 神犇拿到了 uoi 的 ra(镭牌)后,立刻拉着基友小 A 到了一家……餐馆,很低端的那种。

uim 指着墙上的价目表(太低级了没有菜单),说:“随便点”。

题目描述

不过 uim 由于买了一些书,口袋里只剩 M 元 (M≤10000)。

餐馆虽低端,但是菜品种类不少,有 N 种 (N≤100),第 i 种卖 ai​ 元 (ai​≤1000)。由于是很低端的餐馆,所以每种菜只有一份。

小 A 奉行“不把钱吃光不罢休”的原则,所以他点单一定刚好把 uim 身上所有钱花完。他想知道有多少种点菜方法。

由于小 A 肚子太饿,所以最多只能等待 1 秒。

输入格式

第一行是两个数字,表示 N 和 M。

第二行起 N 个正数 ai​(可以有相同的数字,每个数字均在 1000 以内)。

输出格式

一个正整数,表示点菜方案数,保证答案的范围在 int 之内。

输入输出样例

输入 #1

4 4
1 1 2 2

输出 #1

3

思路:这道题没法用深度遍历完成,最后一个测试点会超时,因此可以用背包dp遍历数组完成。


import java.io.*;
public class Main {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StreamTokenizer st = new StreamTokenizer(br);
	static int ini()throws IOException {
		st.nextToken();
		return (int)st.nval;
	}
	static int a[] = new int[105];
	static int f[][] = new int[105][10005];
	static int N,M;
	public static void main(String[] args) throws IOException {
		N = ini(); M = ini();
		for (int i = 1; i <= N; i++)a[i] = ini();
		for (int i = 1; i <= N; i++) {	//种类
			for (int j = 1; j <= M; j++) {	//价格 两种情况,1——f[i-1][j]的可能性 2——f[i-1][j-a[i]]
				if(a[i] == j) {	//如果新菜品的价格刚好等于钱包的金额,那么第二种可能只能为1
					f[i][j] = f[i-1][j] + 1;
				}else if(a[i] > j) {//如果新菜品的价格大于钱包的余额,那么第二种可能性为0,因为买不起
					f[i][j] = f[i-1][j];
				}else {
					f[i][j] = f[i-1][j] + f[i-1][j-a[i]];
				}
			}
		}
		System.out.println(f[N][M]);
	}
	
}

你可能感兴趣的:(算法)