动态规划解决01背包问题

时间:2022-07-16 18:45:12

一、问题描述:有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;
}

四、运行结果如下

动态规划解决01背包问题

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