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
| 講義内容目次 | 菅沼ホーム | 前ページ | 次ページ |