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,說明計算正確!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM