数字的组合(背包方案)

问题 AH: 【基础】数字的组合

题目描述

给定N个正整数A1,A2,…,AN,从中选出若干个数,使它们的和为M,求有多少种选择方案。

注意:选择不同位置的,但值相同的数,认为是不同的方案。

比如:有3个数1 1 1,要组合出2,那么有3个方案,分别是选第1、2个数,选第1、3个数,选第2、3个数。

输入

第一行包含两个整数N和M。

第二行包含N个整数,表示A1,A2,…,AN。

数据范围
1≤N≤100,
1≤M≤10000,
1≤Ai≤1000

输出

包含一个整数,表示可选方案数(本题的计算结果一定在int范围内)。

样例输入

4 4
1 1 2 2

样例输出

3

分析

虽然做出来了,但是状态转移方程是凑出来的,没有很好理解,所以写出来重新整理一下思路.
本题求恰好装满M容量的方案数,以此每个状态dp[i][j]表示为前i个物品恰好装满j容量的方案数量,那么边界为dp[0][0] = 10个物品恰好需要0容量的方案数为1,那么对于第i个物品,有两种状态,第一种:选择第i个物品,那么方案数等于dp[i-1][j-a[i]]i-1个物品恰好使用j-a[i]容量的方案数 ; 第二种状态是不选择物品i,那么它的方案数就等于dp[i-1][j],前i-1物品恰好使用j容量的方案数.假如a[i] = 6,那么dp[i][6] = dp[i-1][0],而dp[i-1][0] = dp[i-2][0] = .... = dp[0][0] = 1,也就是如果容量恰好等于第i个物品的花费,那么可以直接选择它,方案数为1,不用专门初始化,那对于出现多次相同花费的方案a[i] = a[j] = a[k] = 6的话,dp[k][6] = dp[k-1][0](选择k) + dp[k-1][6](不选),而不选k的方案就包括前面选择ij的两种情况,所有是可以计算所有选择方案的

代码

int a[105];
int dp[105][10005];
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    //
    // freopen("E:/Code/C++/untitled1/input.txt","r",stdin);
    // freopen("output.txt","w",stdout);

    int n,m;
    cin >>  n >> m;
    //memset(dp,-1,sizeof(dp));
    f(i,1,n+1) cin >> a[i];
    dp[0][0] = 1;             //初始化
    for(int i = 1;i <= n;++i)
        for(int j = 0;j <= m;++j)
            if(j >= a[i]) dp[i][j] = dp[i-1][j] + dp[i-1][j-a[i]];   //选择i的方案 + 不选
            else dp[i][j] = dp[i-1][j];

    cout << dp[n][m];
}
posted @   bakul  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示