昨日同窗要我幫他看一道算法,以下:ios
是否是乍一看是「0-1揹包」問題呀,我也這麼想,因而就這麼興致勃勃的開始用這個想法去思考怎麼算。可是算法也忘得差很少,回去趕忙補補,也趁着此次機會好好複習一下算法,因而以爲「0-1揹包」問題實現了,這個問題也差很少了吧:
/***********************0-1揹包*************************************/算法
1 //先將那兩個條件忽略,單純利用動態規劃 -------------------這裏就看出有多傻-—_-- 2 //利用動態規劃求解 3 #include <iostream> 4 #define MAX_NUM 50 5 #define MAX_WEIGHT 100 6 using namespace std; 7 8 //動態規劃求解 9 int zero_one_pack(int total_weight, int w[], int v[], int flag[], int n) { 10 int c[MAX_NUM + 1][MAX_WEIGHT + 1] = { 0 }; //c[i][j]表示前i個物體放入容量爲j的揹包得到的最大價值 11 // c[i][j] = max{c[i-1][j], c[i-1][j-w[i]]+v[i]} 12 //第i件物品要麼放,要麼不放 13 //若是第i件物品不放的話,就至關於求前i-1件物體放入容量爲j的揹包得到的最大價值 14 //若是第i件物品放進去的話,就至關於求前i-1件物體放入容量爲j-w[i]的揹包得到的最大價值 15 for (int i = 1; i <= n; i++) { 16 for (int j = 1; j <= total_weight; j++) { 17 if (w[i] > j ) { 18 // 說明第i件物品大於揹包的重量,放不進去 19 c[i][j] = c[i - 1][j]; 20 } 21 22 else { 23 //說明第i件物品的重量小於揹包的重量,因此能夠選擇第i件物品放仍是不放 24 if (c[i - 1][j] > v[i] + c[i - 1][j - w[i]]) { 25 c[i][j] = c[i - 1][j]; 26 } 27 else { 28 c[i][j] = v[i] + c[i - 1][j - w[i]]; 29 } 30 } 31 } 32 } 33 34 //下面求解哪一個物品應該放進揹包 35 int i = n, j = total_weight; 36 while (c[i][j] != 0) { 37 if (c[i - 1][j - w[i]] + v[i] == c[i][j]) { 38 // 若是第i個物體在揹包,那麼顯然去掉這個物品以後,前面i-1個物體在重量爲j-w[i]的揹包下價值是最大的 39 flag[i] = 1; 40 j -= w[i]; 41 } 42 --i; 43 } 44 return c[n][total_weight]; 45 } 46 47 //回溯法求解 48 49 int main() { 50 int total_weight = 60; 51 int w[7] = { 0,7, 10, 4, 9, 3,6 }; 52 int v[7] = { 0,4, 5, 2, 3, 1 ,2}; 53 int flag[7]; //flag[i][j]表示在容量爲j的時候是否將第i件物品放入揹包 54 int total_value = zero_one_pack(total_weight, w, v, flag, 6); 55 cout << "須要放入的物品以下" << endl; 56 for (int i = 1; i <= 6; i++) { 57 if (flag[i] == 1) 58 cout << i << "重量爲" << w[i] << ", 價值爲" << v[i] << endl; 59 } 60 cout << "總的價值爲: " << total_value << endl; 61 system("pause"); 62 return 0; 63 }
查看一下結果,函數
臥槽,瞎了。揹包值這麼大原來!因而乎仍是想着如何利用「0-1揹包」解決,但越想越不對勁,要讓程序記住全部路徑而後根據條件進行篩選,發現是在太過於複雜。但什麼算法能夠呢,因而想到了N皇后問題,介於設置的最大載重量太大,不具表明性,因而大大減小最大載重量,設計一下,行表示要存放的對象,列用1,0表示是否要放入,利用不斷的回溯遞歸取得全部可能的值,再選擇最大值:spa
/***********************N皇后*****************************************/設計
1 #include <iostream> 2 using namespace std; 3 4 int total_weight = 35; //修改最大值 5 int w[7] = { 0, 7, 10, 4, 9, 3, 6 }; 6 int v[7] = { 0, 4, 5, 2, 3, 1, 2 }; 7 int result[7] = { 0 }; 8 int result_all[10][7] ;//用於存儲全部的可能結果 9 int indi = 0; //結果指針 10 int num = 6; 11 12 13 int sumV(); 14 int sumW(int n); 15 16 //判斷下一個是否符合條件 17 bool judge(int n) 18 { 19 if (n == 4) 20 { 21 if (result[4] >= result[1]) 22 return true; 23 else 24 return false; 25 26 } 27 if (n == 5) 28 { 29 if ((result[5] + result[3]) == 1) 30 return true; 31 else 32 return false; 33 } 34 35 if (sumW(n) > total_weight) 36 return false; 37 return true; 38 } 39 40 //主要的遞歸調用函數 41 void backtrack(int n) 42 { 43 if (n > num) 44 45 { 46 47 for (int i = 1; i <= num; i++) 48 { 49 result_all[indi][i] = result[i]; 50 } 51 indi++; 52 } 53 54 else 55 { 56 for (int i = 1; i >= 0; i--) 57 { 58 result[n] = i; 59 if (judge(n)) 60 backtrack(n+1); 61 } 62 } 63 } 64 65 //計算綜價值 66 int sumV( ) 67 { 68 int m = 0; 69 for (int i = 1; i <= num; i++) 70 { 71 if (result[i] == 1) 72 m += v[i]; 73 } 74 return m; 75 } 76 //計算重量 77 int sumW(int n) 78 { 79 int m = 0; 80 for (int i = 1; i <= n; i++) 81 { 82 if (result[i] == 1) 83 m += w[i]; 84 } 85 return m; 86 } 87 88 int main() 89 { 90 backtrack(1); 91 92 //計算最大值 93 int most = 0; 94 int pos = 0; 95 for (int i = 0; i < indi; i++) 96 { 97 int temp = 0; 98 for (int j = 1; j <= num; j++) 99 { 100 if (result_all[i][j] == 1) 101 temp += v[j]; 102 } 103 if (temp>most) 104 { 105 most = temp; 106 pos = i; 107 108 } 109 } 110 111 cout << "最大值是:"<<most<<endl; 112 cout << "結果是:" << endl; 113 for (int i = 1; i <= num; i++) 114 { 115 cout << result_all[pos][i]<<" "; 116 } 117 cout << endl; 118 system("pause"); 119 }
結果:3d
因此說啊,算法死記硬背是沒啥用的,還得看具體狀況來,算法還得多學,此次教訓大了。指針