P1164 小A点菜

题目背景

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

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

题目描述

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

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

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

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

输入输出格式

输入格式:

 

第一行是两个数字,表示 NNN 和 MMM 。

第二行起 NNN 个正数 aia_iai​ (可以有相同的数字,每个数字均在 100010001000 以内)。

 

输出格式:

 

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

 

输入输出样例

输入样例#1: 复制

4 4
1 1 2 2

输出样例#1: 复制

3

简单的01背包问题:

#include
#include
#include
#include
using namespace std;
int dp[110][10010] = { 0 };
int a[110];
int N, M;
/*吃与不吃的问题(状态转移)
        1.j==a[i](嘿,得逞了)dp[i+1][j] = dp[i][j]+1;
        2.j>a[i](嗯,钱还够,可以吃)dp[i+1][j] =dp[i][j] + dp[i][j-a[i]]
        3.j> N >> M;
    for (int i = 0; i < N; i++)
    {
        cin >> a[i];
    }
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j <= M; j++)
        {
            if (j == a[i])
            {
                dp[i + 1][j] = dp[i][j] + 1;
            }
            if (j > a[i])
            {
                dp[i + 1][j] =dp[i][j]+dp[i][j - a[i]];
            }
            if(j

优化:

 

#include
#include
#include
#include
using namespace std;
int dp[10010] = { 0 };
int a[110];
int N, M;
//2.dp[j]+=dp[j-a[i]];    dp[0] =1;当钱量用光加一
int main()
{
	cin >> N >> M;
	for (int i = 0; i < N; i++)
	{
		cin >> a[i];
	}
	dp[0] = 1;
	for (int i = 0; i < N; i++)
	{
		for (int j = M; j >= a[i]; j--)
		{
			dp[j] += dp[j - a[i]];
		}
	}
	cout << dp[M] << endl;;
	return 0;
}

 

你可能感兴趣的:(P1164 小A点菜)