0-1揹包

問題描述 
      給定n種物品和一揹包,物品i的重量是wi,其價值爲vi,揹包的容量爲C。問應如何選擇裝入揹包的物品(物品不能分割),使得裝入揹包中物品的總價值最大? 

抽象描述: 
     x[n]:表示物品的選擇,x[i]=1表示選擇放進物品i到揹包中。 
           
  
 問題分析: 
         1.抽象以後揹包問題轉換爲找到一個最優的數組,x1,x2,.....,xn的0-1序列。 
         
         2.假設最優解的序列爲x1,x2,.....,xn,能使揹包容量C的總價值最大.
 
               若是,x1=1,則x2,...,xn是C-w1容量的揹包的總價值依然是 最大的序列; 
               若是,x1=0,則x2,....,xn是C容量的揹包的總價值依然是 最大的序列。 
           這就是咱們所說的最優子結構性質。 
         
         3.進一步分析:咱們用m(i,j)表示爲已經判斷好了i:n的序列的揹包最大價值,而且此時的揹包剩餘的容量爲j,對物品i進行判斷
 
                若是j>wi, 就只要作出選擇wi和不選擇wi狀況下,哪一種更能使揹包的總價值更大:m(i,j)=max{ m(i+1,j),m(i+1,j-wi)+vi}(注意這是個遞歸式) 
                若是j<wi:       m(i,j)=m(i+1,j) 
                初始化:        m(n,j)=vn  (j>= wn); 
                                m(n,j)=0   (0<=j< wn) 
                                m(0,C)=0    
             最終的結果:m(1,C) 

        4.依次咱們就獲得了一個遞歸的表達式: 
                 
       
       5.若是單純的從利用遞歸,重複計算了不少的值,耗費的時間是很大的,動態規劃還需避免這種重複計算,怎樣自頂向下或自底向上的計算呢?
 
          採用列表的方法就能夠很好的分析設計自頂向下或自底向上的計算的算法了 

 舉例分析: 
         n=3,c=6,w={4,3,2} v={5,2,1} 
         m[i][j]=max{ m[i+1][j], m[i+1][j-w[i]]+v[i] } 
         列表以下: 
         

          最左邊箭頭:咱們計算的方向,從第3行開始向上計算法值。 
          表中紅色箭頭是咱們經過選擇作出的結果:列如 m[2][3]=max{m[3][3],m[3][3-w[2]]+v[2]},咱們最終選擇了m[3][3-w[2]]+v[2]。 
          整個問題的最優解保存在m[1][6]中。ios


#include <iostream> #include <vector>
using namespace std; int maxPrice(int n, int c, vector<int> vecw, vector<int> vecp); int main() { //物品的數量和揹包的容量
    int n, c, weight, price; //得到n個物體的重量和價值,n,c都爲0的時候結束
    cin >> n >> c; while( n != 0 && c != 0 ) { // 物品的重量vecw和物體的價值vecp
        vector<int> vecw, vecp; for (int i = 0; i < n; ++i) { cin >> weight; vecw.push_back(weight); } for (int j = 0; j < n; ++j) { cin >> price; vecp.push_back(price); } //找到價值的最大值
        int max_Price = maxPrice(n, c, vecw, vecp); cout << max_Price << endl; cin >> n >> c; } return 0; } int maxPrice(int n, int c, vector<int> vecw, vector<int> vecp) { int price = 0, flag = 0; if (c == 0) return 0; for(int l = 0; l < n; ++l)//測試是否有能裝入包中的數據
        if (vecw[l] < c) { flag = 1; break; } if (flag == 0)  //若是沒有能裝入包中的數據就返回 0
        return 0; for(int i = 0; i < n; ++i) { int weight = c; weight -= vecw[i]; if (weight >= 0) { vector<int> vec_w, vec_p; for (int j= 0; j < n; ++j) if ( i != j)//建立一個新的數組存儲下一組數據
 { vec_w.push_back(vecw[j]); vec_p.push_back(vecp[j]); } int current =  vecp[i] + maxPrice(n-1, weight, vec_w, vec_p);//遞歸求最大值
            if ( price < current) price = current; } } return price; }

運行結果:算法

 

相關文章
相關標籤/搜索