天天看點

0-1knapbag

狀态轉換方程: 

          f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}

       動态規劃是用空間換時間的一種方法的抽象。其關鍵是發現子問題和記錄其結果。然後利用這些結果減輕運算量。

比如01背包問題。

因為背包最大容量M未知。是以,我們的程式要從1到M一個一個的試。比如,開始任選N件物品的一個。看對應M的背包,能不能放進去,如果能放進去,并且還有多的空間,則,多出來的空間裡能放N-1物品中的最大價值。怎麼能保證總選擇是最大價值呢?看下表。

測試資料:

10,3

3,4

4,5

5,6

c[i][j]數組儲存了1,2,3号物品依次選擇後的最大價值.

這個最大價值是怎麼得來的呢?從背包容量為0開始,1号物品先試,0,1,2,的容量都不能放.是以置0,背包容量為3則裡面放4.這樣,這一排背包容量 為4,5,6,....10的時候,最佳方案都是放4.假如1号物品放入背包.則再看2号物品.當背包容量為3的時候,最佳方案還是上一排的最價方案c為 4.而背包容量為5的時候,則最佳方案為自己的重量5.背包容量為7的時候,很顯然是5加上一個值了。加誰??很顯然是7-4=3的時候.上一排c3的最 佳方案是4.是以。總的最佳方案是5+4為9.這樣.一排一排推下去。最右下放的資料就是最大的價值了。(注意第3排的背包容量為7的時候,最佳方案不是 本身的6.而是上一排的9.說明這時候3号物品沒有被選.選的是1,2号物品.是以得9.)

從以上最大價值的構造過程中可以看出。

f(n,m)=max{f(n-1,m), f(n-1,m-w[n])+P(n,m)}這就是書本上寫的動态規劃方程.

//knapsack.in

10 3

3 4

4 5

5 6

//knapsack.cpp

/*

* File:knapsack.cpp

* Descripe: Dynamic programming

*          transform function:f[i][j]=max{ (f[i-1][j-weight[i]]+v[i]),f[i-1][j]}

* Athor: [email protected]

*     

* */

#include <fstream>

#include <iostream>

using namespace std;

const int Max_value=1000;

ifstream fin("knapsack.in");

ofstream fout("knapsack.out");

int main()

{

    int t,m,i,j,l;

    int *weight,*v,**f;

    fin>>t>>m;      //get the max volum,and the goods number.

    /* new array ,according as the given number*/

    weight = new int[m+1];

    memset(weight,0,m+1);

    v = new int[m+1];

    f=new int*[m+1];   

    for(i=0;i<m+1;i++)

    {

        f[i]=new int[Max_value]; 

        memset(f[i],0,Max_value);

    }

//    fout<<"sizeof:"<<sizeof(weight)<<endl;

    //read test cases

    fout<<t<<" "<<m<<endl;        

    for(i=1;i<=m;i++)

        fin>>weight[i]>>v[i];

        fout<<weight[i]<<" "<<v[i]<<endl;

    //Dynamic programming ,according to translation function

          for(j=1;j<=t;j++)                    

        if (weight[i]<=j && (l=f[i-1][j-weight[i]]+v[i])>f[i-1][j])

            f[i][j]=l;

        else f[i][j]=f[i-1][j];       

       fout<<"The max velue:"<<f

[t];

       delete weight,v;

       for(int i=0;i<m+1;i++)

           delete f[i];

       delete f;

       return 0;

}

       以上隻是一個簡單的說明事例,具體的動态規劃問題,需要具體分析,得出狀态轉換方程,并依據方程修改程式。

#include <fstream>

#include <iostream>

using namespace std;

const int Max_value=1000;

ifstream fin("knapsack.in");

ofstream fout("knapsack.out");

int main()

{

    int t,goodnum,i,j,l;

    int *weight,*value,**f;

    fin >> t >> goodnum;   // t=10 and m=3   //get the max volum,and the goods number.

    /* new array ,according as the given number*/

    weight = new int[goodnum+1];//動态生成一個數組,存放物品的重量

    memset(weight,0,goodnum+1);//設定為零

    value = new int[goodnum+1];//申請一個一維數組,存放物品的價值

    memset(weight,0,goodnum+1);//初始化為零

    f=new int*[goodnum+1];   //f 指向 int*

    for(i=0;i<goodnum+1;i++)//二維數組初始化

    {

        f[i]=new int[Max_value]; 

        memset(f[i],0,Max_value);

    }

//    fout<<"sizeof:"<<sizeof(weight)<<endl;

繼續閱讀