P1164 小A点菜 - 洛谷 | 计算机科学教育新生态
题目背景
uim 神犇拿到了 uoi 的 ra(镭牌)后,立刻拉着基友小 A 到了一家……餐馆,很低端的那种。
uim 指着墙上的价目表(太低级了没有菜单),说:“随便点”。
题目描述
不过 uim 由于买了一些书,口袋里只剩 M 元(M ≤ 10000)。
餐馆虽低端,但是菜品种类不少,有 N 种(N ≤ 100),第 i 种卖 a_i 元(a_i ≤ 1000)。由于是很低端的餐馆,所以每种菜只有一份。
小 A 奉行“不把钱吃光不罢休”的原则,所以他点单一正好把 uim 身上所有钱花完。他想知道有多少种点菜方法。
由于小 A 肚子太饿,所以最多只能等待 1 秒。
输入格式
第一行是两个数字,表示 N 和 M。
第二行起 N 个正数 a_i(可以有相同的数字,每个数字均在 1000 以内)。
输出格式
一个正整数,表示点菜方案数,保证答案的范围在 int 之内。
输入输出样例
输入 #1
4 4
1 1 2 2
输出 #1
3
说明/提示
2020.8.29,增添一组 hack 数据 by @yummy
思路:
代码如下:
记忆化搜索:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;typedef long long ll;
const int N = 1e4 + 10;
int n, m;
int value[N];
int mem[N][N]; // 表示第 i 个物品,剩余 j 时的方案数int dfs(int x, int SP)
{//cout << x << "------" << SP << endl;int sum = 0;if (mem[x][SP]) return mem[x][SP];if (SP == 0) return 1; if (x > n) return 0;if (SP >= value[x]) sum = dfs(x + 1, SP - value[x]) + dfs(x + 1, SP); else sum = dfs(x + 1, SP); mem[x][SP] = sum; return sum;
}int main() {cin >> n >> m;for (int i = 1; i <= n; i++){cin >> value[i];}memset(mem, 0, sizeof(mem));cout << dfs(1, m);return 0;
}
dp:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;typedef long long ll;
const int N = 1e4 + 10;
int n, m;
int value[N];
int f[N][N]; // 表示第 i 个物品,剩余 j 时的方案数int main()
{cin >> n >> m;for (int i = 1; i <= n; i++){cin >> value[i];}f[n+1][0] = 1; for(int i = n ; i >= 1 ; i--){for(int j = 0 ; j <= m ; j++){if(j >= value[i])f[i][j] = f[i+1][j-value[i]] + f[i+1][j];elsef[i][j] = f[i+1][j]; } } cout << f[1][m];return 0;
}
dp2:
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;typedef long long ll;
const int N = 1e4 + 10;
int n, m;
int value[N];
int dp[N][N]; // dp[i][j] 表示前 i 个物品,背包容量为 j 时的方案数int main() {cin >> n >> m;// 输入物品价值for (int i = 1; i <= n; i++) {cin >> value[i];}// 初始化 dp 数组memset(dp, 0, sizeof(dp));dp[0][0] = 1; // 没有物品时,背包容量为 0 的方案数为 1// 动态规划计算for (int i = 1; i <= n; i++) {for (int j = 0; j <= m; j++) {if (j >= value[i]) dp[i][j] = dp[i-1][j - value[i]] + dp[i-1][j]; // 选择当前物品elsedp[i][j] = dp[i-1][j]; // 不选择当前物品}}// 输出结果cout << dp[n][m];return 0;
}