C-01揹包問題

【聲明】:很是感謝http://blog.sina.com.cn/s/blog_6dcd26b301013810.html,給我帶來的幫助。html

看這個圖片表示的意思:web

w[i]表示第i件物品的容積 ,p[i]第i件物品的價值。數組

c[i][j] 表示 第i件物品裝入容積爲j 的空間中的最高價值。 其中i是物品編號,j表明當前揹包的容積。優化

很是重要的狀態轉移方程:spa

  C[i][j] = max(C[i-1][j],C[i-1][j-w[i]]+p[i])code

C[i-1][j]表示放第i-1件物品,揹包容量爲j的總價值。orm

C[i-1][j-w[i]]表示存放第i-1件物品,揹包容量爲  j-w[i] 的總價值;再加上當前第i件物品的價值htm

【也就是說在選擇是否是要放一件物品時,就看看不放該物件的價值 與 放了該物件的總價值 哪一個更大一點的問題。】blog

 

int knapsack(int m,int n)//總容量,物品數量
{
    int i,j,w[10],p[10];//每件物品的容量個價值
    for(i=1;i<n+1;i++)
    scanf("\n%d,%d",&w[i],&p[i]);

    for(i=0;i<10;i++)
        for(j=0;j<100;j++)
            c[i][j]=0;

    for(i=1;i<n+1;i++)//數量
        for(j=1;j<m+1;j++)
        {
            if(w[i]<=j){//j表示當前容量,當前容量若是小於該件物品的容量,
                        //也就是該件物品放不進去揹包
                 if(p[i]+c[i-1][j-w[i]]>c[i-1][j])
                     c[i][j]=p[i]+c[i-1][j-w[i]];
                 else
                     c[i][j]=c[i-1][j];
            }else

                 c[i][j]=c[i-1][j];
         }
     return(c[n][m]);
}

 

 

 01圖片

因爲使用一維數組解01揹包會被屢次用到,徹底揹包的一種優化實現方式也是使用一維數組,因此咱們有必要理解這種方法。

若是隻使用一維數組f[0…v],咱們要達到的效果是:

第i次循環結束後f[v]中所表示的就是使用二維數組時的f[i][v],即前i個物體面對容量v時的最大價值。

咱們知道f[v]是由兩個狀態得來的,f[i-1][v]和f[i-1][v-c[i]],使用一維數組時,當第i次循環以前時,f[v]實際上就是f[i-1][v],那麼怎麼獲得第二個子問題(f[i-1][v-c[i]])的值呢?事實上,若是在每次循環中咱們以v=V…0的順序推f[v]時,就能保證f[v-c[i]]存儲的是f[i-1][v-c[i]]的狀態。狀態轉移方程爲:

v = V...0; f(v) = max{ f(v), f(v-c[i])+w[i] }

咱們能夠與二維數組的狀態轉移方程對比一下

f(i,v) = max{ f(i-1,v), f(i-1,v-c[i])+w[i] }

 

 

仍是看上圖:若是按照v=0-V的順序的話,第一件物品存入包中和上圖同樣,當存入第二件物品的時候,v= 4時,價值爲5。可是沒有辦法準確知道f[i-1][v-c[i]](即f[v-c[i])。【因爲是一維數組,數據會被覆蓋】

可是,若是按照v = V--0的順序。存入第一件物品的時候,和上圖是同樣的,此時f[10] = ...=f[5] = 4,開始存放第二件物品的時候,v =V = 10;f(v) = max{ f(v), f(v-c[i])+w[i] }(即f[10] = max{f[10],f[10-c[2]+w[2]} = max{f[10],f[6]+w[2] = max{4,4+5} = 9);v = 9……以此類推就能夠得出上圖中的第二行。

 【再想不明白,本身按照上圖執行一遍便可。】

 程序代碼:

#include<stdio.h>
#include<stdlib.h>
#define MAXN 100+10

int f[MAXN];
int w[MAXN],c[MAXN];

int main()
{
    int N,V;
    int i=0,j;
    scanf("%d%d",&V,&N);
    for(i = 0;i<N;i++)
    {
        scanf("%d%d",&c[i],&w[i]);
    }
    memset(f,0,sizeof(f));
    for(i = 0;i<N;i++)
        for(j = V;j>=c[i];j--)
        {
           f[j] = f[j]>(f[j-c[i]]+w[i]) ? f[j]: f[j-c[i]]+w[i];
        }

    printf("max value si %d\n",f[V]);
    return 0;
}

這樣一來就所有解決了問題了………………^__^

相關文章
相關標籤/搜索