問題描述:ios
給定n種物品和一揹包。物品i的重量是wi,其價值爲vi,揹包的容量爲C。問:應該如何選擇裝入揹包的物品,是的裝入揹包中物品的總價值最大?算法
細節須知:windows
暫無。app
算法原理:spa
a.最優子結構性質設計
0-1揹包問題具備最優子結構性質。設(y1,y2,…,yn)是所給0-1揹包問題的一個最優解,則(y2,…,yn)是下面相應子問題的一個最優解。code
b.遞歸關係orm
設所給0-1揹包問題的子問題blog
的最優值爲m(i,j),即m(i,j)是揹包容量爲j,可選擇物品爲i,i+1,…,n時0-1揹包問題的最優值。有0-1揹包問題的最優子結構性質,能夠創建以下計算m(i,j)的遞歸式遞歸
1 #include <iostream> 2 #include <fstream> 3 #include <ctime> 4 #include <algorithm> 5 #include <windows.h> 6 using namespace std; 7 #define N 10000 8 9 //int w[5] = { 0 , 2 , 3 , 4 , 5 }; //商品的體積二、三、四、5 10 //int v[5] = { 0 , 3 , 4 , 5 , 6 }; //商品的價值三、四、五、6 11 //int bagV = 8; //揹包大小 12 int dp[N][N]; //動態規劃表 13 //int item[5]; //最優解狀況 14 15 void findMax(int k,int n,int w[],int v[]) { //動態規劃 16 for (int i = 1; i <= k; i++) { 17 for (int j = 1; j <= n; j++) { 18 if (j < w[i]) 19 dp[i][j] = dp[i - 1][j]; 20 else 21 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i]] + v[i]); 22 } 23 } 24 } 25 26 void findWhat(int i, int j,int w[],int v[],int item[]) { //最優解狀況 27 if (i > 0) { 28 if (dp[i][j] == dp[i - 1][j]) { 29 item[i] = 0; 30 findWhat(i - 1, j,w,v,item); 31 } 32 else if (j - w[i] >= 0 && dp[i][j] == dp[i - 1][j - w[i]] + v[i]) { 33 item[i] = 1; 34 findWhat(i - 1, j - w[i],w,v,item); 35 } 36 } 37 } 38 39 void print(int k,int n,int item[]) { 40 /*for (int i = 0; i < k+1; i++) { //動態規劃表輸出 41 for (int j = 0; j < n+1; j++) { 42 cout << dp[i][j] << ' '; 43 } 44 cout << endl; 45 } 46 cout << endl;*/ 47 cout <<"The item number that should be put into the backpack is:"; 48 for (int i = 0; i < k+1; i++){ //最優解輸出 49 if(item[i] == 1) 50 cout << i << ' '; 51 } 52 cout << endl; 53 } 54 55 int main(void) 56 { 57 LARGE_INTEGER nFreq; 58 LARGE_INTEGER nBeginTime; 59 LARGE_INTEGER nEndTime; 60 ofstream fout; 61 double cost; 62 int i,j,m,n,k; 63 cout << "Please enter the number of times you want to run the program:"; 64 cin >> m; 65 //int object_amount[m]; 66 //double runtime[m]; 67 fout.open("backpack.txt",ios::app); 68 if(!fout){ 69 cerr<<"Can not open file 'backpack.txt' "<<endl; 70 return -1; 71 } 72 fout.setf(ios_base::fixed,ios_base::floatfield); //防止輸出的數字使用科學計數法 73 srand((unsigned int)time(NULL)); 74 for(i = 0; i < m; i++){ 75 n = rand()%10000; 76 k = rand()%10000; 77 //object_amount[i] = k; 78 fout<<k<<","; 79 int item[k]; 80 cout << "The " << i+1 << "th test's backpack lattice number is:" << n << endl; 81 cout << "The " << i+1 << "th test's object amount is:" << k << endl; 82 int w[k]; 83 int v[k]; 84 memset(dp,0,sizeof(dp)); 85 w[0] = 0; 86 v[0] = 0; 87 for(j=1;j<k;j++){ 88 w[j]=rand()%100; 89 v[j]=rand()%1000; 90 } 91 QueryPerformanceFrequency(&nFreq); 92 QueryPerformanceCounter(&nBeginTime); 93 findMax(k,n,w,v); 94 findWhat(k,n,w,v,item); 95 print(k,n,item); 96 QueryPerformanceCounter(&nEndTime); 97 cost=(double)(nEndTime.QuadPart - nBeginTime.QuadPart) / (double)nFreq.QuadPart; 98 //runtime[i]=cost; 99 fout<<cost<<endl; 100 cout<<"The running time is:"<<cost<<" s"<<endl; 101 } 102 /* fout.open("backpack.txt",ios::app); 103 if(!fout){ 104 cerr<<"Can not open file 'backpack.txt' "<<endl; 105 return -1; 106 } 107 fout.setf(ios_base::fixed,ios_base::floatfield); //防止輸出的數字使用科學計數法 108 for(i=0;i<m;i++){ 109 fout<<object_amount[i]<<","<<runtime[i]<<endl; 110 }*/ 111 fout.close(); 112 cout<<"Success!"<<endl; 113 return 0; 114 }
程序設計思路:
根據算法原理中所述遞歸關係,遞歸計算所有的m(i,j),獲得不一樣狀況下的最優解。
假設m[1][c]給出所要求的的0-1揹包問題的最優值。相應的最優解計算以下:
若是m[1][c]=m[2][c],則x1=0;不然x1=1.當x1=0是,由m[2][c]繼續構造最優解;當x1=1時,有m[2][c-w1]繼續構造最優解。以此類推,可構造出相應的最優解(x1,x2,…,xn)。
時間複雜性分析:
從計算m(i,j)的遞歸式容易看出,對於0-1揹包問題的求解算法須要O(nc)計算時間,而算法解出最優方案須要O(n)計算時間,當揹包容量c很大時,算法須要的計算時間較多。
生成的數據可導入EXCEL中進行數據分析生成分析圖表。