算法实践:林克的背包 (动态规划)

林克的背包

描述

林克拥有一个可扩容的背包,前提是需要有足够的克罗克果实。

林克当前背包的总容积是70。

假设在道具商店里有n种道具,假设每个道具的体积分别是a1,a2……an。

请问,要塞满林克的背包一共有多少种不同方法呢?

输入

输入的第一行是正整数n (1 <= n <= 50),表示不同的道具的数目。

接下来的n行,每行有一个1到70之间的正整数,表示不同道具的体积值a1,a2……an。

输出

输出塞满林克的背包的总方式数。

样例

13
30
28
64
58
9
66
28
63
34
10
27
28
30
2

难度

中等,动态规划

解释

递归方程

如果没有容积放 放法为1

如果没有物品放 放法为0

第j个物品,放法为 当前物品放入背包的方法+不放入背包的方法

递归方程中含有重复计算的子问题,采用动态规划填表法,d[i,j]代表容积为i的背包放j种道具的方法数

递推式: d[i,j] = d[i,j-1] + d[i-道具空间,j]

代码

#include <iostream>
using namespace std;
#define  BAGSIZE  70
int bags(int daoju[],int n){
    int dp[BAGSIZE+1][n+1];
    for(int j=0;j<=BAGSIZE;j++)  //表格第一列,道具为0,放法为0
        dp[j][0] = 0;
    for(int i=0;i<=n;i++)     //表格第一行,空间为0,放法为1
        dp[0][i] = 1;
    for(int i=1;i<=BAGSIZE;i++){
        for(int j=1;j<=n;j++){
            dp[i][j] = dp[i][j-1];
            if(i-daoju[j]>=0)
                dp[i][j] += dp[i-daoju[j]][j-1];
        }
    }
    for(int i=0;i<=BAGSIZE;i++){
        for(int j=0;j<=n;j++)
            cout<<dp[i][j]<<' ';
        cout<<endl;
    }
    return dp[BAGSIZE][n];
}

int main() {
    int n;
    cin>>n;
    int daoju[n+1];
    daoju[0] = 0;
    for(int i=1;i<=n;i++)
        cin>>daoju[i];
    cout<<bags(daoju,n);
    return 0;
}
发布了129 篇原创文章 · 获赞 148 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/matafeiyanll/article/details/105079220