0-1背包问题

0-1背包问题是典型的动态规划问题,看了好多博客和书面教材,一直是似懂非懂的感觉,自从看了一部教学视频以后,感觉恍然大悟,讲的确实非常通俗易懂,而且有写代码的过程,非常推荐!!

 

http://www.tudou.com/listplay/Z-bWgybEtig/XaOy3xM2klU.html

其实0-1背包问题可以抽象成一个小偷拿着一个容量有限(容量设为W)的背包去商店偷东西,每个商品都有自己的体积w和价值v,小偷的目的就是用这个容量有限的背包装满价值总量最大的东西。

为了讨论方便,我们限定一个具体的背景,不妨设背包容量W=20,

要偷的东西的体积w和价值v分别如下:

商品名称k 体积w 价值v
0

2

3
1 3 4
2 4 5
3 5 8
4 9 10

当计算完B(0,2)时,按原路返回,最后得到B(4,20)。

下表是0-1背包解题过程表,可以用来记录每一步的计算过程。

#include<stdio.h>
int n,c,bestp;//物品的个数,背包的容量,最大价值
int p[10000],w[10000],x[10000],bestx[10000];//物品的价值,物品的重量,x[i]暂存物品的选中情况,物品的选中情况

void Backtrack(int i,int cp,int cw)
{ //cw当前包内物品重量,cp当前包内物品价值
    int j;
    if(i>n)//回溯结束
    {
        if(cp>bestp)
        {
            bestp=cp;
            for(i=0;i<=n;i++) bestx[i]=x[i];
        }
    }
    else 
        for(j=0;j<=1;j++)  
        {
            x[i]=j;
            if(cw+x[i]*w[i]<=c)  
            {
                cw+=w[i]*x[i];
                cp+=p[i]*x[i];
                Backtrack(i+1,cp,cw);
                cw-=w[i]*x[i];
                cp-=p[i]*x[i];
            }
        }
}

int main()
{
    int i;
    bestp=0; 
    printf("请输入背包最大容量:\n");
    scanf("%d",&c);
    printf("请输入物品个数:\n");
    scanf("%d",&n);
    printf("请依次输入物品的重量:\n");
    for(i=1;i<=n;i++) 
        scanf("%d",&w[i]);
    printf("请依次输入物品的价值:\n");
    for(i=1;i<=n;i++) 
        scanf("%d",&p[i]);
    Backtrack(1,0,0);
    printf("最大价值为:\n");
    printf("%d\n",bestp);
    printf("被选中的物品依次是(0表示未选中,1表示选中)\n");
    for(i=1;i<=n;i++) 
        printf("%d ",bestx[i]);
    printf("\n");
    return 0;
}

程序运行结果如下:

与计算表格的右下角的值一样,同为26,说明计算正确!

posted @ 2016-05-15 20:33  一一一匹马赛克儿  阅读(4123)  评论(0编辑  收藏  举报