01 /****************************/ 02 /* 横型探索(幅優先探索) */ 03 /* coded by Y.Suganuma */ 04 /****************************/ 05 #include <stdio.h> 06 #include <queue> 07 08 using namespace std; 09 10 void print(queue<char> &q) { 11 printf(" queue の状態: "); 12 if (q.empty()) 13 printf("空です\n"); 14 else 15 printf("先頭及び最後尾: %c %c, 要素数: %d\n", q.front(), q.back(), q.size()); 16 } 17 18 int main() 19 { 20 queue<char> q; 21 22 printf("S の追加\n"); 23 q.push('S'); 24 print(q); 25 26 printf("先頭 S を削除し,A, B, C を追加\n"); 27 q.pop(); 28 q.push('A'); 29 q.push('B'); 30 q.push('C'); 31 print(q); 32 33 printf("先頭 A を削除し,D, E を追加\n"); 34 q.pop(); 35 q.push('D'); 36 q.push('E'); 37 print(q); 38 39 printf("先頭 B を削除\n"); 40 q.pop(); 41 print(q); 42 43 printf("先頭 C を削除し,F, G を追加\n"); 44 q.pop(); 45 q.push('F'); 46 q.push('G'); 47 print(q); 48 49 printf("先頭 D を削除\n"); 50 q.pop(); 51 print(q); 52 53 printf("先頭 E を削除\n"); 54 q.pop(); 55 print(q); 56 57 printf("先頭 F を削除\n"); 58 q.pop(); 59 print(q); 60 61 printf("先頭 G を削除\n"); 62 q.pop(); 63 print(q); 64 65 return 0; 66 }
S の追加 queue の状態: 先頭及び最後尾: S S, 要素数: 1 先頭 S を削除し,A, B, C を追加 queue の状態: 先頭及び最後尾: A C, 要素数: 3 先頭 A を削除し,D, E を追加 queue の状態: 先頭及び最後尾: B E, 要素数: 4 先頭 B を削除 queue の状態: 先頭及び最後尾: C E, 要素数: 3 先頭 C を削除し,F, G を追加 queue の状態: 先頭及び最後尾: D G, 要素数: 4 先頭 D を削除 queue の状態: 先頭及び最後尾: E G, 要素数: 3 先頭 E を削除 queue の状態: 先頭及び最後尾: F G, 要素数: 2 先頭 F を削除 queue の状態: 先頭及び最後尾: G G, 要素数: 1 先頭 G を削除 queue の状態: 空です
01 /****************************/ 02 /* 縦型探索(深さ優先探索) */ 03 /* coded by Y.Suganuma */ 04 /****************************/ 05 #include <stdio.h> 06 #include <stack> 07 08 using namespace std; 09 10 void print(stack<char> &q) { 11 printf(" stack の状態: "); 12 if (q.empty()) 13 printf("空です\n"); 14 else 15 printf("先頭: %c, 要素数: %d\n", q.top(), q.size()); 16 } 17 18 int main() 19 { 20 stack<char> q; 21 22 printf("S の追加\n"); 23 q.push('S'); 24 print(q); 25 26 printf("先頭 S を削除し,A, B, C を追加\n"); 27 q.pop(); 28 q.push('A'); 29 q.push('B'); 30 q.push('C'); 31 print(q); 32 33 printf("先頭 C を削除し,F, G を追加\n"); 34 q.pop(); 35 q.push('F'); 36 q.push('G'); 37 print(q); 38 39 printf("先頭 G を削除\n"); 40 q.pop(); 41 print(q); 42 43 printf("先頭 F を削除\n"); 44 q.pop(); 45 print(q); 46 47 printf("先頭 B を削除\n"); 48 q.pop(); 49 print(q); 50 51 printf("先頭 A を削除し,D, E を追加\n"); 52 q.pop(); 53 q.push('D'); 54 q.push('E'); 55 print(q); 56 57 printf("先頭 E を削除\n"); 58 q.pop(); 59 print(q); 60 61 printf("先頭 D を削除\n"); 62 q.pop(); 63 print(q); 64 65 return 0; 66 }
S の追加 stack の状態: 先頭: S, 要素数: 1 先頭 S を削除し,A, B, C を追加 stack の状態: 先頭: C, 要素数: 3 先頭 C を削除し,F, G を追加 stack の状態: 先頭: G, 要素数: 4 先頭 G を削除 stack の状態: 先頭: F, 要素数: 3 先頭 F を削除 stack の状態: 先頭: B, 要素数: 2 先頭 B を削除 stack の状態: 先頭: A, 要素数: 1 先頭 A を削除し,D, E を追加 stack の状態: 先頭: E, 要素数: 2 先頭 E を削除 stack の状態: 先頭: D, 要素数: 1 先頭 D を削除 stack の状態: 空です
001 /*********************************/ 002 /* 横型探索(8パズル) */ 003 /* coded by Y.Suganuma */ 004 /*********************************/ 005 #include <stdio.h> 006 #include <queue> 007 #include <map> 008 #include <string> 009 010 using namespace std; 011 012 class Depth 013 { 014 public: 015 int dep; 016 string prev; 017 Depth (string str, int dep1) 018 { 019 prev = str; // 前の状態 020 dep = dep1; // 深さ 021 } 022 }; 023 024 /********************************/ 025 /* コマの移動 */ 026 /* str : 現在の状態 */ 027 /* res : 移動後の状態 */ 028 /* return : 移動後の状態数 */ 029 /********************************/ 030 int move(string str, string *res) 031 { 032 int k, n = 0; 033 string str1; 034 035 k = str.find("0"); 036 switch(k) { 037 case 0: 038 str1 = str.replace(k, 1, str, k+3, 1); 039 str1 = str1.replace(k+3, 1, 1, '0'); 040 res[n] = str1; 041 n++; 042 str1 = str.replace(k, 1, str, k+1, 1); 043 str1 = str1.replace(k+1, 1, 1, '0'); 044 res[n] = str1; 045 n++; 046 break; 047 case 1: 048 str1 = str.replace(k, 1, str, k+3, 1); 049 str1 = str1.replace(k+3, 1, 1, '0'); 050 res[n] = str1; 051 n++; 052 str1 = str.replace(k, 1, str, k-1, 1); 053 str1 = str1.replace(k-1, 1, 1, '0'); 054 res[n] = str1; 055 n++; 056 str1 = str.replace(k, 1, str, k+1, 1); 057 str1 = str1.replace(k+1, 1, 1, '0'); 058 res[n] = str1; 059 n++; 060 break; 061 case 2: 062 str1 = str.replace(k, 1, str, k+3, 1); 063 str1 = str1.replace(k+3, 1, 1, '0'); 064 res[n] = str1; 065 n++; 066 str1 = str.replace(k, 1, str, k-1, 1); 067 str1 = str1.replace(k-1, 1, 1, '0'); 068 res[n] = str1; 069 n++; 070 break; 071 case 3: 072 str1 = str.replace(k, 1, str, k-3, 1); 073 str1 = str1.replace(k-3, 1, 1, '0'); 074 res[n] = str1; 075 n++; 076 str1 = str.replace(k, 1, str, k+3, 1); 077 str1 = str1.replace(k+3, 1, 1, '0'); 078 res[n] = str1; 079 n++; 080 str1 = str.replace(k, 1, str, k+1, 1); 081 str1 = str1.replace(k+1, 1, 1, '0'); 082 res[n] = str1; 083 n++; 084 break; 085 case 4: 086 str1 = str.replace(k, 1, str, k-3, 1); 087 str1 = str1.replace(k-3, 1, 1, '0'); 088 res[n] = str1; 089 n++; 090 str1 = str.replace(k, 1, str, k+3, 1); 091 str1 = str1.replace(k+3, 1, 1, '0'); 092 res[n] = str1; 093 n++; 094 str1 = str.replace(k, 1, str, k-1, 1); 095 str1 = str1.replace(k-1, 1, 1, '0'); 096 res[n] = str1; 097 n++; 098 str1 = str.replace(k, 1, str, k+1, 1); 099 str1 = str1.replace(k+1, 1, 1, '0'); 100 res[n] = str1; 101 n++; 102 break; 103 case 5: 104 str1 = str.replace(k, 1, str, k-3, 1); 105 str1 = str1.replace(k-3, 1, 1, '0'); 106 res[n] = str1; 107 n++; 108 str1 = str.replace(k, 1, str, k+3, 1); 109 str1 = str1.replace(k+3, 1, 1, '0'); 110 res[n] = str1; 111 n++; 112 str1 = str.replace(k, 1, str, k-1, 1); 113 str1 = str1.replace(k-1, 1, 1, '0'); 114 res[n] = str1; 115 n++; 116 break; 117 case 6: 118 str1 = str.replace(k, 1, str, k-3, 1); 119 str1 = str1.replace(k-3, 1, 1, '0'); 120 res[n] = str1; 121 n++; 122 str1 = str.replace(k, 1, str, k+1, 1); 123 str1 = str1.replace(k+1, 1, 1, '0'); 124 res[n] = str1; 125 n++; 126 break; 127 case 7: 128 str1 = str.replace(k, 1, str, k-3, 1); 129 str1 = str1.replace(k-3, 1, 1, '0'); 130 res[n] = str1; 131 n++; 132 str1 = str.replace(k, 1, str, k-1, 1); 133 str1 = str1.replace(k-1, 1, 1, '0'); 134 res[n] = str1; 135 n++; 136 str1 = str.replace(k, 1, str, k+1, 1); 137 str1 = str1.replace(k+1, 1, 1, '0'); 138 res[n] = str1; 139 n++; 140 break; 141 case 8: 142 str1 = str.replace(k, 1, str, k-3, 1); 143 str1 = str1.replace(k-3, 1, 1, '0'); 144 res[n] = str1; 145 n++; 146 str1 = str.replace(k, 1, str, k-1, 1); 147 str1 = str1.replace(k-1, 1, 1, '0'); 148 res[n] = str1; 149 n++; 150 break; 151 } 152 153 return n; 154 } 155 156 /*************************/ 157 /* 横型探索(8パズル) */ 158 /* start : 初期状態 */ 159 /* goal : 目標状態 */ 160 /*************************/ 161 void width(string start, string goal) 162 { 163 int i1, n, node1 = 1, node2 = 0, dep = 1, ct = 1; 164 string str, res[4]; 165 queue<pair<string, int> > q; 166 map<string, Depth> m; 167 map<string, Depth>::iterator it; 168 169 m.insert(pair<string, Depth>(start, Depth("",dep))); 170 q.push(pair<string, int>(start, dep)); 171 while (!q.empty()) { 172 str = q.front().first; 173 dep = q.front().second; 174 node2++; 175 // ゴール 176 if (str == goal) { 177 ct = dep; 178 break; 179 } 180 // ゴールでない 181 // コマを移動し,同じ状態のものがなければキューに追加 182 else { 183 q.pop(); 184 n = move(str, res); 185 for (i1 = 0; i1 < n; i1++) { 186 it = m.find(res[i1]); // 同じ状態か? 187 if (it == m.end()) { 188 m.insert(pair<string, Depth>(res[i1], Depth(str,dep+1))); 189 q.push(pair<string, int>(res[i1], dep+1)); 190 node1++; 191 } 192 } 193 } 194 } 195 // 結果の出力 196 printf(" 展開とチェック: %d %d, 最短距離: %d\n", node1, node2, ct); 197 while (str.length() > 0) { 198 printf("\n %c %c %c\n", str.at(0), str.at(1), str.at(2)); 199 printf(" %c %c %c\n", str.at(3), str.at(4), str.at(5)); 200 printf(" %c %c %c\n", str.at(6), str.at(7), str.at(8)); 201 it = m.find(str); 202 str = ((*it).second).prev; 203 } 204 } 205 206 int main() 207 { 208 string goal = "123804765"; 209 210 printf("例1\n"); 211 string start = "283164705"; 212 width(start, goal); 213 214 printf("例2\n"); 215 start = "216408753"; 216 width(start, goal); 217 218 return 0; 219 }
例1 展開とチェック: 62 35, 最短距離: 6 1 2 3 8 0 4 7 6 5 1 2 3 0 8 4 7 6 5 0 2 3 1 8 4 7 6 5 2 0 3 1 8 4 7 6 5 2 8 3 1 0 4 7 6 5 2 8 3 1 6 4 7 0 5 例2 展開とチェック: 34299 22912, 最短距離: 19 1 2 3 8 0 4 7 6 5 1 2 3 8 4 0 7 6 5 1 2 0 8 4 3 7 6 5 1 0 2 8 4 3 7 6 5 1 4 2 8 0 3 7 6 5 1 4 2 8 6 3 7 0 5 1 4 2 8 6 3 7 5 0 1 4 2 8 6 0 7 5 3 1 4 2 8 0 6 7 5 3 1 4 2 0 8 6 7 5 3 0 4 2 1 8 6 7 5 3 4 0 2 1 8 6 7 5 3 4 2 0 1 8 6 7 5 3 4 2 6 1 8 0 7 5 3 4 2 6 1 0 8 7 5 3 4 2 6 0 1 8 7 5 3 0 2 6 4 1 8 7 5 3 2 0 6 4 1 8 7 5 3 2 1 6 4 0 8 7 5 3
f(n) = g(n) + h(n) g(n): 節点 n の深さ h(n) = p(n) + 3s(n) p(n): 各コマの正しい位置からの距離を加えた値 s(n): 中心以外のコマに対し,その次のコマが正しい順序になっていなければ 2, そうでなければ 0,中心の駒には 1 を与える事によって得られる得点
001 /*********************************/ 002 /* 知識を用いた探索(8パズル) */ 003 /* coded by Y.Suganuma */ 004 /*********************************/ 005 #include <stdio.h> 006 #include <queue> 007 #include <map> 008 #include <string> 009 010 using namespace std; 011 012 class Node 013 { 014 public: 015 int dep, est; 016 string str; 017 Node (string str1, int dep1, int est1) 018 { 019 str = str1; // 状態 020 dep = dep1; // 深さ 021 est = est1; // 評価値 022 } 023 }; 024 025 class Depth 026 { 027 public: 028 int dep, est; 029 string prev; 030 Depth (string prev1, int dep1, int est1) 031 { 032 prev = prev1; // 前の状態 033 dep = dep1; // 深さ 034 est = est1; // 評価値 035 } 036 }; 037 038 bool operator< (Node n1, Node n2) 039 { 040 bool sw = true; 041 if (n1.est == n2.est) 042 sw = (n1.str < n2.str) ? true : false; 043 else 044 sw = (n1.est > n2.est) ? true : false; 045 return sw; 046 } 047 048 /************************/ 049 /* ノードの評価 */ 050 /* dep : 深さ */ 051 /* str : 状態 */ 052 /* goal : 目標状態 */ 053 /* return : 評価値 */ 054 /************************/ 055 int estimation(int dep, string str, string goal) 056 { 057 int i1, i2, i3, i4, k1, k2, pi = dep, sw; 058 char cg[3][3], cn[3][3]; 059 060 for (i1 = 0; i1 < 9; i1++) { 061 k1 = i1 / 3; 062 k2 = i1 - 3 * k1; 063 cg[k1][k2] = goal.at(i1) - '0'; 064 } 065 for (i1 = 0; i1 < 9; i1++) { 066 k1 = i1 / 3; 067 k2 = i1 - 3 * k1; 068 cn[k1][k2] = str.at(i1) - '0'; 069 } 070 071 for (i1 = 0; i1 < 3; i1++) { 072 for (i2 = 0; i2 < 3; i2++) { 073 sw = 1; 074 for (i3 = 0; i3 < 3 && sw > 0; i3++) { 075 for (i4 = 0; i4 < 3 && sw > 0; i4++) { 076 if (cg[i3][i4] == cn[i1][i2]) { 077 sw = 0; 078 pi += (abs(i3-i1) + abs(i4-i2)); 079 } 080 } 081 } 082 } 083 } 084 085 if (cn[1][1] != '0') 086 pi++; 087 if (cn[0][1] != (cn[0][0]+1)%9) 088 pi += 2; 089 if (cn[0][2] != (cn[0][1]+1)%9) 090 pi += 2; 091 if (cn[1][2] != (cn[0][2]+1)%9) 092 pi += 2; 093 if (cn[2][2] != (cn[1][2]+1)%9) 094 pi += 2; 095 if (cn[2][1] != (cn[2][2]+1)%9) 096 pi += 2; 097 if (cn[2][0] != (cn[2][1]+1)%9) 098 pi += 2; 099 if (cn[1][0] != (cn[2][0]+1)%9) 100 pi += 2; 101 if (cn[0][0] != (cn[1][0]+1)%9) 102 pi += 2; 103 104 return pi; 105 } 106 107 /********************************/ 108 /* コマの移動 */ 109 /* str : 現在の状態 */ 110 /* res : 移動後の状態 */ 111 /* return : 移動後の状態数 */ 112 /********************************/ 113 int move(string str, string *res) 114 { 115 int k, n = 0; 116 string str1; 117 118 k = str.find("0"); 119 switch(k) { 120 case 0: 121 str1 = str.replace(k, 1, str, k+3, 1); 122 str1 = str1.replace(k+3, 1, 1, '0'); 123 res[n] = str1; 124 n++; 125 str1 = str.replace(k, 1, str, k+1, 1); 126 str1 = str1.replace(k+1, 1, 1, '0'); 127 res[n] = str1; 128 n++; 129 break; 130 case 1: 131 str1 = str.replace(k, 1, str, k+3, 1); 132 str1 = str1.replace(k+3, 1, 1, '0'); 133 res[n] = str1; 134 n++; 135 str1 = str.replace(k, 1, str, k-1, 1); 136 str1 = str1.replace(k-1, 1, 1, '0'); 137 res[n] = str1; 138 n++; 139 str1 = str.replace(k, 1, str, k+1, 1); 140 str1 = str1.replace(k+1, 1, 1, '0'); 141 res[n] = str1; 142 n++; 143 break; 144 case 2: 145 str1 = str.replace(k, 1, str, k+3, 1); 146 str1 = str1.replace(k+3, 1, 1, '0'); 147 res[n] = str1; 148 n++; 149 str1 = str.replace(k, 1, str, k-1, 1); 150 str1 = str1.replace(k-1, 1, 1, '0'); 151 res[n] = str1; 152 n++; 153 break; 154 case 3: 155 str1 = str.replace(k, 1, str, k-3, 1); 156 str1 = str1.replace(k-3, 1, 1, '0'); 157 res[n] = str1; 158 n++; 159 str1 = str.replace(k, 1, str, k+3, 1); 160 str1 = str1.replace(k+3, 1, 1, '0'); 161 res[n] = str1; 162 n++; 163 str1 = str.replace(k, 1, str, k+1, 1); 164 str1 = str1.replace(k+1, 1, 1, '0'); 165 res[n] = str1; 166 n++; 167 break; 168 case 4: 169 str1 = str.replace(k, 1, str, k-3, 1); 170 str1 = str1.replace(k-3, 1, 1, '0'); 171 res[n] = str1; 172 n++; 173 str1 = str.replace(k, 1, str, k+3, 1); 174 str1 = str1.replace(k+3, 1, 1, '0'); 175 res[n] = str1; 176 n++; 177 str1 = str.replace(k, 1, str, k-1, 1); 178 str1 = str1.replace(k-1, 1, 1, '0'); 179 res[n] = str1; 180 n++; 181 str1 = str.replace(k, 1, str, k+1, 1); 182 str1 = str1.replace(k+1, 1, 1, '0'); 183 res[n] = str1; 184 n++; 185 break; 186 case 5: 187 str1 = str.replace(k, 1, str, k-3, 1); 188 str1 = str1.replace(k-3, 1, 1, '0'); 189 res[n] = str1; 190 n++; 191 str1 = str.replace(k, 1, str, k+3, 1); 192 str1 = str1.replace(k+3, 1, 1, '0'); 193 res[n] = str1; 194 n++; 195 str1 = str.replace(k, 1, str, k-1, 1); 196 str1 = str1.replace(k-1, 1, 1, '0'); 197 res[n] = str1; 198 n++; 199 break; 200 case 6: 201 str1 = str.replace(k, 1, str, k-3, 1); 202 str1 = str1.replace(k-3, 1, 1, '0'); 203 res[n] = str1; 204 n++; 205 str1 = str.replace(k, 1, str, k+1, 1); 206 str1 = str1.replace(k+1, 1, 1, '0'); 207 res[n] = str1; 208 n++; 209 break; 210 case 7: 211 str1 = str.replace(k, 1, str, k-3, 1); 212 str1 = str1.replace(k-3, 1, 1, '0'); 213 res[n] = str1; 214 n++; 215 str1 = str.replace(k, 1, str, k-1, 1); 216 str1 = str1.replace(k-1, 1, 1, '0'); 217 res[n] = str1; 218 n++; 219 str1 = str.replace(k, 1, str, k+1, 1); 220 str1 = str1.replace(k+1, 1, 1, '0'); 221 res[n] = str1; 222 n++; 223 break; 224 case 8: 225 str1 = str.replace(k, 1, str, k-3, 1); 226 str1 = str1.replace(k-3, 1, 1, '0'); 227 res[n] = str1; 228 n++; 229 str1 = str.replace(k, 1, str, k-1, 1); 230 str1 = str1.replace(k-1, 1, 1, '0'); 231 res[n] = str1; 232 n++; 233 break; 234 } 235 236 return n; 237 } 238 239 /********************************/ 240 /* 知識を用いた探索(8パズル) */ 241 /* start : 初期状態 */ 242 /* goal : 目標状態 */ 243 /********************************/ 244 void intel(string start, string goal) 245 { 246 int i1, n, node1 = 1, node2 = 0, dep = 1, ct = 1, est; 247 string str, res[4]; 248 priority_queue<Node> p; 249 map<string, Depth> m; 250 map<string, Depth>::iterator it; 251 bool sw; 252 253 est = estimation(dep, start, goal); 254 m.insert(pair<string, Depth>(start, Depth("",dep,est))); 255 p.push(Node(start,dep,est)); 256 while (!p.empty()) { 257 str = p.top().str; 258 dep = p.top().dep; 259 node2++; 260 // ゴール 261 if (str == goal) { 262 ct = dep; 263 break; 264 } 265 // ゴールでない 266 // コマを移動し,同じ状態のものがなければキューに追加 267 else { 268 p.pop(); 269 n = move(str, res); 270 for (i1 = 0; i1 < n; i1++) { 271 sw = true; 272 est = estimation(dep+1, res[i1], goal); 273 it = m.find(res[i1]); // 同じ状態か? 274 if (it != m.end()) { 275 if (est < ((*it).second).est) 276 m.erase(it); 277 else 278 sw = false; 279 } 280 if (sw) { 281 m.insert(pair<string, Depth>(res[i1], Depth(str,dep+1,est))); 282 p.push(Node(res[i1], dep+1, est)); 283 node1++; 284 } 285 } 286 } 287 } 288 // 結果の出力 289 printf(" 展開とチェック: %d %d, 最短距離: %d\n", node1, node2, ct); 290 while (str.length() > 0) { 291 printf("\n %c %c %c\n", str.at(0), str.at(1), str.at(2)); 292 printf(" %c %c %c\n", str.at(3), str.at(4), str.at(5)); 293 printf(" %c %c %c\n", str.at(6), str.at(7), str.at(8)); 294 it = m.find(str); 295 str = ((*it).second).prev; 296 } 297 } 298 299 int main() 300 { 301 string goal = "123804765"; 302 303 printf("例1\n"); 304 string start = "283164705"; 305 intel(start, goal); 306 307 printf("例2\n"); 308 start = "216408753"; 309 intel(start, goal); 310 311 return 0; 312 }
例1 展開とチェック: 12 6, 最短距離: 6 1 2 3 8 0 4 7 6 5 1 2 3 0 8 4 7 6 5 0 2 3 1 8 4 7 6 5 2 0 3 1 8 4 7 6 5 2 8 3 1 0 4 7 6 5 2 8 3 1 6 4 7 0 5 例2 展開とチェック: 201 111, 最短距離: 19 1 2 3 8 0 4 7 6 5 1 0 3 8 2 4 7 6 5 0 1 3 8 2 4 7 6 5 8 1 3 0 2 4 7 6 5 8 1 3 2 0 4 7 6 5 8 1 3 2 4 0 7 6 5 8 1 0 2 4 3 7 6 5 8 0 1 2 4 3 7 6 5 0 8 1 2 4 3 7 6 5 2 8 1 0 4 3 7 6 5 2 8 1 4 0 3 7 6 5 2 8 1 4 6 3 7 0 5 2 8 1 4 6 3 7 5 0 2 8 1 4 6 0 7 5 3 2 8 1 4 0 6 7 5 3 2 0 1 4 8 6 7 5 3 2 1 0 4 8 6 7 5 3 2 1 6 4 8 0 7 5 3 2 1 6 4 0 8 7 5 3
投資額: x | 1 | 2 | 3 | 4 |
---|---|---|---|---|
1 番目の投資先へ投資したときの利益: f1(x) | 8 | 18 | 22 | 24 |
2 番目の投資先へ投資したときの利益: f2(x) | 3 | 6 | 9 | 12 |
3 番目の投資先へ投資したときの利益: f3(x) | 6 | 7 | 8 | 10 |
001 /**********************************/ 002 /* 動的計画法(資源配分問題) */ 003 /* coded by Y.Suganuma */ 004 /**********************************/ 005 #include <stdio.h> 006 007 /*****************************************/ 008 /* 動的計画法による資源配分問題 */ 009 /* p : 現在計算中の投資先 */ 010 /* n_toshi : 投資先の数 */ 011 /* step : 資金の投資単位 */ 012 /* n_case : 資金の投資ケース数 */ 013 /* table : 投資先,投資金額毎の利益 */ 014 /* rieki : 現段階の最大利益(φ) */ 015 /* next : 最大利益を与える投資先 */ 016 /* coded by Y.Suganuma */ 017 /*****************************************/ 018 int dynamic(int p, int n_toshi, int step, int n_case, int **table, int **rieki, int **next) 019 { 020 int m = 0; 021 // 最大利益の計算 022 // 1段目 023 if (p == 0) { 024 for (int i1 = 0; i1 < n_case; i1++) 025 rieki[p][i1] = table[p][i1]; 026 } 027 // 2段目以降 028 else { 029 for (int i1 = 0; i1 < n_case; i1++) { 030 m = step * i1; // 投資額 031 int l1 = -1; // rieki[p][i1] は, 032 int l2 = -1; // table[p][l1] + rieki[p-1][l2] で最大 033 int max = -1; 034 int m1 = 0; 035 int k1 = 0; 036 while (m1 <= m) { 037 int m2 = 0; // 前段 038 int k2 = 0; // 前段 039 while (m1+m2 <= m) { 040 int r = table[p][k1] + rieki[p-1][k2]; 041 if (r > max) { 042 l1 = k1; 043 l2 = k2; 044 max = r; 045 } 046 m2 += step; 047 k2++; 048 } 049 m1 += step; 050 k1++; 051 } 052 next[p][i1] = l2; 053 if (l2 >= 0) 054 rieki[p][i1] = table[p][l1] + rieki[p-1][l2]; 055 } 056 } 057 // 次の投資先 058 // 最終段より前 059 if (p < n_toshi-1) 060 m = dynamic(p+1, n_toshi, step, n_case, table, rieki, next); 061 // 最終段 062 else { 063 int max = -1; 064 int k1 = n_toshi - 1; 065 for (int i1 = 0; i1 < n_case; i1++) { 066 if (next[k1][i1] >= 0 && rieki[k1][i1] > max) { 067 max = rieki[k1][i1]; 068 m = i1; 069 } 070 } 071 } 072 073 return m; 074 } 075 076 int main() 077 { 078 // データの入力と領域の確保 079 int n_toshi = 3; // 投資先 080 int step = 1; // 投資単位 081 int n_case = 5; // 資金の投資ケース数 082 int **table = new int * [n_toshi]; // 投資先,投資額,そのときの利益 083 int **rieki = new int * [n_toshi]; // 現段階の最大利益 084 int **next = new int * [n_toshi]; // 最大利益を与える投資先 085 for (int i1 = 0; i1 < n_toshi; i1++) { 086 table[i1] = new int [n_case]; 087 rieki[i1] = new int [n_case]; 088 next[i1] = new int [n_case]; 089 } 090 table[0][0] = 0; 091 table[0][1] = 8; 092 table[0][2] = 18; 093 table[0][3] = 22; 094 table[0][4] = 24; 095 table[1][0] = 0; 096 table[1][1] = 3; 097 table[1][2] = 6; 098 table[1][3] = 9; 099 table[1][4] = 12; 100 table[2][0] = 0; 101 table[2][1] = 6; 102 table[2][2] = 7; 103 table[2][3] = 8; 104 table[2][4] = 10; 105 // 実行 106 int max = dynamic(0, n_toshi, step, n_case, table, rieki, next); 107 // 結果の出力 108 if (max >= 0) { 109 printf("最大利益 %d\n", rieki[n_toshi-1][max]); 110 for (int i1 = n_toshi-1; i1 >= 0; i1--) { 111 int k = max * step; 112 if (i1 > 0) { 113 max = next[i1][max]; 114 k -= max * step; 115 } 116 printf(" 投資先 %d 投資資金 %d\n", i1+1, k); 117 } 118 } 119 else 120 printf("解が存在しません!\n"); 121 122 return 0; 123 }
最大利益 28 投資先 3 投資資金 1 投資先 2 投資資金 0 投資先 1 投資資金 3
01 /********************************************/ 02 /* 横型探索(最短経路) */ 03 /* n : ノードの数 */ 04 /* ノード0:スタート */ 05 /* ノード(n-1):ゴール */ 06 /* r : ノード間の距離 */ 07 /* rd : 現時点におけるノードまでの距離 */ 08 /* coded by Y.Suganuma */ 09 /********************************************/ 10 #include <stdio.h> 11 #include <queue> 12 13 using namespace std; 14 15 void width(int n, int **r, int *rd) 16 { 17 int node = 1; 18 queue<pair<int, int> > q; 19 20 q.push(pair<int, int>(0, 0)); 21 while (!q.empty()) { 22 int k = q.front().first; // ノード番号 23 int v = q.front().second; // スタートノードからの距離 24 q.pop(); 25 // 先頭のノードから到達可能なノードをキューに追加 26 // (既にノードまでの距離が計算済みであり,その 27 // 距離が今回計算した距離よりも短い場合は除く) 28 for (int i1 = 0; i1 < n; i1++) { 29 if (r[k][i1] >= 0) { 30 int r1 = v + r[k][i1]; 31 if (rd[i1] < 0 || r1 < rd[i1]) { 32 q.push(pair<int, int>(i1, r1)); 33 rd[i1] = r1; 34 node++; 35 } 36 } 37 } 38 } 39 40 printf("展開したノード数: %d, 最短距離: %d\n", node, rd[n-1]); 41 } 42 43 int main() 44 { 45 int *rd = new int [7]; // ノードまでの距離 46 int **r = new int * [7]; // ノード間距離 47 for (int i1 = 0; i1 < 7; i1++) { 48 rd[i1] = -1; 49 r[i1] = new int [7]; 50 for (int i2 = 0; i2 < 7; i2++) 51 r[i1][i2] = -1; 52 } 53 rd[0] = 0; 54 r[0][1] = 2; 55 r[1][0] = 2; 56 r[0][2] = 5; 57 r[2][0] = 5; 58 r[1][2] = 4; 59 r[2][1] = 4; 60 r[1][3] = 6; 61 r[3][1] = 6; 62 r[1][4] = 10; 63 r[4][1] = 10; 64 r[2][3] = 2; 65 r[3][2] = 2; 66 r[3][5] = 1; 67 r[5][3] = 1; 68 r[4][5] = 3; 69 r[5][4] = 3; 70 r[4][6] = 5; 71 r[6][4] = 5; 72 r[5][6] = 9; 73 r[6][5] = 9; 74 75 width(7, r, rd); 76 77 return 0; 78 }
展開したノード数: 11, 最短距離: 16
001 /****************************/ 002 /* Dijkstra(最短経路) */ 003 /* coded by Y.Suganuma */ 004 /****************************/ 005 #include <stdio.h> 006 #include <set> 007 008 using namespace std; 009 010 class Net 011 { 012 public : 013 int node; // ノード番号 014 int r; // スタートからの距離 015 Net (int n1, int r1) 016 { 017 node = n1; 018 r = r1; 019 } 020 }; 021 022 bool operator< (Net n1, Net n2) 023 { 024 if (n1.r == n2.r) 025 return (n1.node < n2.node) ? true : false; 026 else 027 return (n1.r < n2.r) ? true : false; 028 } 029 030 /********************************************/ 031 /* Dijkstra(最短経路) */ 032 /* n : ノードの数 */ 033 /* ノード0:スタート */ 034 /* ノード(n-1):ゴール */ 035 /* r : ノード間の距離 */ 036 /* rd : 現時点におけるノードまでの距離 */ 037 /* used : 距離が確定したか否か */ 038 /********************************************/ 039 void Dijkstra(int n, int **r, int *rd, bool *used) 040 { 041 int node = 1; 042 set<Net> s; 043 set<Net>::iterator it; 044 045 s.insert(Net(0, 0)); 046 while (!s.empty()) { 047 it = s.begin(); 048 int k = it->node; // ノード番号 049 int v = it->r; // スタートノードからの距離 050 s.erase(it); 051 if (!used[k]) { 052 // 先頭のノードから到達可能なノードをセットに追加 053 // ・距離が決定しているノードは除く 054 // ・既にノードまでの距離が計算済みであり,その距離が 055 // 今回計算した距離よりも短い場合は距離を修正して追加 056 used[k] = true; 057 for (int i1 = 0; i1 < n; i1++) { 058 if (!used[i1] && r[k][i1] >= 0) { 059 int r1 = v + r[k][i1]; 060 if (rd[i1] < 0 || r1 < rd[i1]) { 061 s.insert(Net(i1, r1)); 062 rd[i1] = r1; 063 node++; 064 } 065 } 066 } 067 } 068 else 069 node--; 070 } 071 072 printf("展開したノード数: %d, 最短距離: %d\n", node, rd[n-1]); 073 } 074 075 int main() 076 { 077 bool *used = new bool [7]; 078 int *rd = new int [7]; // ノードまでの距離 079 int **r = new int * [7]; // ノード間距離 080 for (int i1 = 0; i1 < 7; i1++) { 081 used[i1] = false; 082 rd[i1] = -1; 083 r[i1] = new int [7]; 084 for (int i2 = 0; i2 < 7; i2++) 085 r[i1][i2] = -1; 086 } 087 rd[0] = 0; 088 r[0][1] = 2; 089 r[1][0] = 2; 090 r[0][2] = 5; 091 r[2][0] = 5; 092 r[1][2] = 4; 093 r[2][1] = 4; 094 r[1][3] = 6; 095 r[3][1] = 6; 096 r[1][4] = 10; 097 r[4][1] = 10; 098 r[2][3] = 2; 099 r[3][2] = 2; 100 r[3][5] = 1; 101 r[5][3] = 1; 102 r[4][5] = 3; 103 r[5][4] = 3; 104 r[4][6] = 5; 105 r[6][4] = 5; 106 r[5][6] = 9; 107 r[6][5] = 9; 108 109 Dijkstra(7, r, rd, used); 110 111 return 0; 112 }
展開したノード数: 7, 最短距離: 16
講義内容目次 | 菅沼ホーム | 前ページ | 次ページ |