0
点赞
收藏
分享

微信扫一扫

第一次接触DP

进击的包籽 2022-03-11 阅读 67
算法

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

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

题目描述

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

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

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

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

输入格式

第一行是两个数字,表示NN和MM。

第二行起NN个正数a_iai​(可以有相同的数字,每个数字均在10001000以内)。

输出格式

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

输入输出样例

输入 #1复制

4 4
1 1 2 2

输出 #1复制

3

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <set>
#include <cmath>
#include <map>
typedef long long ll;
using namespace std;
const int N = 505;
const int MAXN = 10000 + 5;


int s[105][10005];
int a[101];

int main() {
	int n, m;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", a + i);
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= m; j++) {
			if (j < a[i]) {
				s[i][j] = s[i - 1][j];
			} else if (j == a[i]) {
				s[i][j] = s[i - 1][j] + 1;
			} else if (j > a[i]) {
				s[i][j] = s[i - 1][j] + s[i - 1][j - a[i]];
			}
		}
	}
	printf("%d", s[n][m]);
	return 0;
}


#if 0//记忆化搜索
int n, m;
int  s[105];
int a[105][10006];
int f(int step, int mony) {
	if (a[step][mony]) {
		return a[step][mony];
	}
	if (s[step] > mony) {
		return 0;
	}
	if (s[step] == mony) {
		return 1;
	}
	for (int i = step + 1; i <= n; i++) {
		a[step][mony] += f(i, mony - s[step]);
	}
	return a[step][mony];
}

int main() {
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", s + i);
	}
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		ans += f(i, m);
	}
	printf("%d", ans);
	return 0;
}
#endif
举报

相关推荐

0 条评论