算法分析:C语言实现动态规划之0-1背包问题

背包问题求解原理:

为了装满背包,我们导出一个递归公式如下,设V[i,j]用来表示从前i项中取出来的装人体积为j的背包的物品的最大价值。这里,i的范围是从О到n,j的范围是从0到C。这样,要寻求的是值 V[n,C]。很清楚,V[o,j]对于所有j的值是0,这是由于背包中什么也没有。另-方面,V[i,0]对于所有i的值为0,因为没有东西可放到为0的背包里。一般情况下,当i和j都大于0时,有下面的结论,它是很容易证明的。

观察结论

1.V[i-1,j]:仅用最优的方法取自的物品去装入体积为j的背包所得到的价值最大值。

2. V[i-1,j- s,]+n:用最优的方法取自的物品去装入体积为j- s;的背包所得到的价值最大值加上物品u;的价值。这仅应用于如果j≥s、以及它等于把物品u加到背包上的情况。

背包问题的递推公式:

 (CSDN导入不了word上写的公式,只能放图片,难受,呜呜┭┮﹏┭┮)

背包容量为10
有4个物品
这四个物品的体积与价值分别为:
2   4   第一件物品
3   2   第二件物品
4   5   第三件物品
6   8   第四件物品   

前n件物品的体积相加应小于等于相应的容量,并在该容量下使相应的价值相加实现最大。

    0   1   2   3   4   5   6   7   8   9   10  //0~10不同容量下分别能装下不同体积的物品
0   0   0   0   0   0   0   0   0   0   0   0   
1   0   0   4   4   4   4   4   4   4   4   4   
2   0   0   4   4   4   6   6   6   6   6   6   
3   0   0   4   4   5   6   9   9   9   11  11  
4   0   0   4   4   5   6   9   9   12  12  13

如上图矩阵

【3,6】指的是前三件物品在容量为6时,实现的最大价值,此时第一件物品与第三件物品的体积相加,价值也相加,此时为5+4=9,虽然容量为6的情况下也可以装下第一件与第二件物品,但这两件物品的价值为4+2=6,没有前者的价值大,所以将9放进,实现该容量下的最大价值。

【4,9】指的是前4件物品在容量为9时,实现的最大价值,此时为第一件和第四件物品的体积相加,虽然不能完全装完背包但此时的价值8+4=12相加最大。在容量为9的情况下,也可以装下第一件、第二件和第三件物品,但这些物品的价值相加为4+2+5=11,12>11所以还是装12,实现该容量下的最大价值。

 代码实现如下:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>


void pack01();
int max(int a,int b);
int main()
{
    pack01();
    return 0;
}
int max(int a,int b)
{
    return a>b?a:b;
}

void pack01()
{
    int *w;
    int *v;
    int i,j,n,c;
    printf("输入背包容量以及物品个数(容量 个数):");
    scanf("%d%d",&c,&n);
    printf("输入各个物品体积以及价值(体积 价值(回车)):\n");
    w=(int* )malloc(n*sizeof(int));
    v=(int* )malloc(n*sizeof(int));
    w[0]=v[0]=0;
    for(i=1;i<n+1;i++){
        scanf("%d%d",&w[i],&v[i]);
    }
    int dp[n+1][c+1];
    for(i=0;i<=n;i++)
        dp[i][0]=0;
    for(j=0;j<=c;j++)
        dp[0][j]=0;
    for(i=1;i<=n;i++)
        for(j=1;j<=c;j++)
        {
            dp[i][j]=dp[i-1][j];
            if(w[i]<=j)
                dp[i][j]=max(dp[i][j],dp[i-1][j-w[i]]+v[i]);
        }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=c;j++)
        {
            printf("%d\t",dp[i][j]);
        }
        printf("\n");
    }
    printf("\n%d\n",dp[n][c]);
    printf("按任意键继续\n");
}

程序实现:

  • 14
    点赞
  • 131
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coolstuz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值