神奇的口袋

原题:

有一个神奇的口袋,总的容积是40,用这个口袋可以变出一些物品,这些物品的总体积必须是40。John现在有n个想要得到的物品,每个物品的体积分别是a1,a2……an。John可以从这些物品中选择一些,如果选出的物体的总体积是40,那么利用这个神奇的口袋,John就可以得到这些物品。现在的问题是,John有多少种不同的选择物品的方式。

一个背包问题 依然是两种解决办法 递推和动归

总感觉递推比较好理解,这道题问的是有多少种方式。状态转移方程:dp(x-1,y-a[i])or dp(x-1, y) x代表物品编号 y代表重量 a是储存重量的数组。可以不选该物品或者选择后重量减去当前物品重量。

#include <iostream>

using namespace std;

#define MAXN 50

int a[MAXN];

int dp(int x, int y){

    if(x < 0){

        return 0;

    }

    if(y == 0){

        return 1;

    }

    return dp(x - 1, y) + dp(x - 1, y - a[x]);

}

int main(int argc, const char * argv[]) {

    int n, i;

    scanf("%d", &n);

    for( i = 1; i <= n; i ++){

        scanf("%d", &a[i]);

        getchar();

    }

    printf("%d\n", dp(n, 40));

    return 0;

}*/

动态规划,要定义二维数组,

dp[w][k]就是从第k个物品开始取得重量为w的方法个数,依然是选或者不选两种情况 但是这两种情况不应该是并列关系吗?这里似乎是先不选 再讨论选?


可以这样想,就理解了:

if( w-a[k] >= 0){ 

dp[w][k] = dp[w][k-1]+ dp[w-a[k]][k-1];  

 }

else dp[w][k] = dp[w][k-1];

#include <iostream>

using namespacestd;

#define MAXN 50

int a[MAXN], dp[MAXN][MAXN];

int main(){

    int n, i, w, k;

    scanf("%d", &n);

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

    for( i =1; i <= n; i ++){

        scanf("%d", &a[i]);

        getchar();

    }

    for( i =1; i <= n; i++){

        dp[0][i] =1;

    }

    dp[0][0] =1;

    for( w =1; w <= 40; w ++){

        for( k =1; k <= n; k ++){

            dp[w][k] =dp[w][k - 1];//??????????????

            if(w >=a[k]){

                dp[w][k] +=dp[w - a[k]][k -1];

            }

        }

    }

    printf("%d\n",dp[40][n]);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值