测试文章标题

发布时间 2023-07-25 18:30:09作者: 爱七宝

你好!

#include <iostream>

#include <cstring>

#include <cstdio>

using namespace std;

/*

    分析:这是一个动态规划问题:

        a. "01背包"——每种菜只有"点或者不点"2个选择,每种菜只有一盘

        b. 滚动数组——因为YS1到10000,N到100,不压缩存储的话dp太大

        c. 恰好装满——要求YS1元钱必须恰好用完

        d. 方案个数——求点菜方案的个数,不是求最大值

    

    例如:dp[10] = 3 表示要恰好用完10元钱,可以有3种点菜方案

    

    1. 状态转移方程

        dp[v] = dp[v] + dp[v-ys1[i]]

    2. 填写顺序:

        i:[1..N]

            v:[YS1, ys1[i]] (如果此处是增序,则变成重复背包了)         

    3. 初值:

        dp[i] = 0 i:[1..YS1]

         设置为0,本题求方案个数,不需要设置成NINF

        dp[0] = 1

        如果一共有0元,那么,"什么都不点"也是1种方案,刚好用完0元        

    4. 结果分析:

     (1) 根据题意,要输出dp[YS1]的值,

         即刚好用完YS1元的点菜方案个数

     (2) 如果dp[i] = 0 ,则表示没办法刚好用完i元

    

    更详细的分析,请看课件    

                

*/

//

int dp[10001];

int ys1[101];

int N, YS1;

 

int main()

{

    cin >>N >>YS1;

    for (int i=1; i<=N; i++) scanf("%d", &ys1[i]);

    

memset(dp, 0, sizeof(dp));

dp[0] = 1;

 

for(int i=1;i<=N;i++)

{

for(int v=YS1;v>=ys1[i];v--) // v不够w[i]的话,dp[v]不会改变。

{

dp[v] = dp[v] + dp[v-ys1[i]];

}

}

 

printf("%d", dp[YS1]);

 

return 0;

}