0-1揹包問題與N皇后問題的糾結

昨日同窗要我幫他看一道算法,以下: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


因此說啊,算法死記硬背是沒啥用的,還得看具體狀況來,算法還得多學,此次教訓大了。指針

相關文章
相關標籤/搜索