动态规划解决01背包问题

一、问题描述:有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和?

二、总体思路:根据动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、判断是否满足最优性原理、找大问题与小问题的递推关系式、填表、寻找解组成)找出01背包问题的最优解以及解组成,然后编写代码实现;

三、c语言代码如下

#include<stdio.h>
int main()
{
    int i,j;  //循环变量
    int bc,n; //bc为背包容量,n为商品数量
    int w[10],v[10];  //w数组存放对应商品的重量,v数组存放对应商品的价值,p数组存放对应商品取的件数
    int bcv[10][10];  //bcv数组存放最佳组合对应的价值
    printf("请输入商品总数:\n");
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        printf("请输入第%d件商品的重量和价值\n",i);
        scanf("%d%d",&w[i],&v[i]);
    }
    printf("请输入背包的总容量:\n");
    scanf("%d",&bc);
    //初始化bcv
    for(i=0;i<10;i++)
    {
        bcv[i][0]=0;
        bcv[0][i]=0;
    }
    printf("商品对应的重量与价值:\n      ");
    for(i=1;i<=n;i++)
        printf("%d ",i);
    printf("\n");
    printf("重量: ");
    for(i=1;i<=n;i++)
        printf("%d ",w[i]);
    printf("\n");
    printf("价值: ");
    for(i=1;i<=n;i++)
        printf("%d ",v[i]);
    printf("\n");
    //找到最佳组合
    for(i=1;i<=n;i++)  //i表示考虑前i个物品
        for(j=1;j<=bc;j++) //j表示当前背包的容量
    {
        if(j<w[i])  //背包容量不够
            bcv[i][j]=bcv[i-1][j];
        else    //背包容量够
        {
            int t=bcv[i-1][j-w[i]]+v[i];  //t为装入i后的价值
            if(bcv[i-1][j]>t)   //不装
                bcv[i][j]=bcv[i-1][j];
            else   //装
            {
                bcv[i][j]=t;
            }
        }
    }
    //找到所取的商品号
    printf("\n最有价值的装法为:\n");
    i=n;
    j=bc;
    while(j>0)
    {
        if(bcv[i][j]>bcv[i-1][j])  //取了
        {
            printf("取第%d件商品\n",i);
            j-=w[i];
        }
        else   //没取
            i--;
    }
    printf("最大价值总和为%d\n",bcv[n][bc]);
    return 0;
}

四、运行结果如下

这里写图片描述

五、分析
动态规划的思想就是面对一个比较复杂的问题的时候首先把问题简单化,先不考虑那么多,只考虑简单的情况。考虑后面的情况的时候可以运用前面已经得到的结果,这样逐步求精,就可以得到最优解。用蛮力法也可以得到最优解,但是蛮力法的时间复杂度太高,没有动态规划的效率高。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值