1/*
2 * ๋นํธ๋ง์คํฌ DP (Bitmask DP)
3 * TSP, Subset Enumeration, Assignment Problem
4 *
5 * ์งํฉ์ ์ํ๋ฅผ ๋นํธ๋ก ํํํ์ฌ DP๋ฅผ ์ํํฉ๋๋ค.
6 */
7
8#include <iostream>
9#include <vector>
10#include <algorithm>
11#include <climits>
12#include <bitset>
13
14using namespace std;
15
16// =============================================================================
17// 1. ๋นํธ ์ฐ์ฐ ๊ธฐ์ด
18// =============================================================================
19
20void bitOperations() {
21 int n = 4; // ์งํฉ ํฌ๊ธฐ
22 int fullSet = (1 << n) - 1; // {0, 1, 2, 3}
23
24 cout << "[1] ๋นํธ ์ฐ์ฐ ๊ธฐ์ด" << endl;
25
26 // ์์ i ํฌํจ ์ฌ๋ถ
27 int set = 0b1010; // {1, 3}
28 cout << " ์งํฉ 1010 (10์ง์: " << set << ")" << endl;
29 cout << " ์์ 1 ํฌํจ: " << ((set & (1 << 1)) ? "์" : "์๋์ค") << endl;
30 cout << " ์์ 2 ํฌํจ: " << ((set & (1 << 2)) ? "์" : "์๋์ค") << endl;
31
32 // ์์ ์ถ๊ฐ/์ ๊ฑฐ
33 set |= (1 << 2); // 2 ์ถ๊ฐ
34 cout << " 2 ์ถ๊ฐ ํ: " << bitset<4>(set) << endl;
35 set &= ~(1 << 1); // 1 ์ ๊ฑฐ
36 cout << " 1 ์ ๊ฑฐ ํ: " << bitset<4>(set) << endl;
37
38 // ์์ ํ ๊ธ
39 set ^= (1 << 3); // 3 ํ ๊ธ
40 cout << " 3 ํ ๊ธ ํ: " << bitset<4>(set) << endl;
41
42 // ์งํฉ ํฌ๊ธฐ (1์ ๊ฐ์)
43 cout << " ์งํฉ ํฌ๊ธฐ: " << __builtin_popcount(set) << endl;
44
45 // ์ตํ์ ๋นํธ
46 cout << " ์ตํ์ 1๋นํธ: " << (set & -set) << endl;
47}
48
49// =============================================================================
50// 2. ๋ถ๋ถ์งํฉ ์ํ
51// =============================================================================
52
53void enumerateSubsets(int n) {
54 cout << "\n[2] ๋ถ๋ถ์งํฉ ์ํ" << endl;
55 cout << " n = " << n << "์ธ ์งํฉ์ ๋ชจ๋ ๋ถ๋ถ์งํฉ:" << endl;
56
57 // ๋ชจ๋ ๋ถ๋ถ์งํฉ
58 cout << " ์ ์ฒด: ";
59 for (int mask = 0; mask < (1 << n); mask++) {
60 cout << bitset<3>(mask) << " ";
61 }
62 cout << endl;
63
64 // ํน์ ์งํฉ์ ๋ถ๋ถ์งํฉ
65 int set = 0b101; // {0, 2}
66 cout << " " << bitset<3>(set) << "์ ๋ถ๋ถ์งํฉ: ";
67 for (int sub = set; ; sub = (sub - 1) & set) {
68 cout << bitset<3>(sub) << " ";
69 if (sub == 0) break;
70 }
71 cout << endl;
72}
73
74// =============================================================================
75// 3. ์ธํ์ ๋ฌธ์ (TSP)
76// =============================================================================
77
78const int INF = INT_MAX / 2;
79
80int tsp(int n, const vector<vector<int>>& dist) {
81 // dp[mask][i]: mask ์งํฉ์ ๋ฐฉ๋ฌธํ๊ณ ํ์ฌ i์ ์์ ๋ ์ต์ ๋น์ฉ
82 vector<vector<int>> dp(1 << n, vector<int>(n, INF));
83
84 dp[1][0] = 0; // ์์์ 0์์ ์ถ๋ฐ
85
86 for (int mask = 1; mask < (1 << n); mask++) {
87 for (int u = 0; u < n; u++) {
88 if (!(mask & (1 << u))) continue;
89 if (dp[mask][u] == INF) continue;
90
91 for (int v = 0; v < n; v++) {
92 if (mask & (1 << v)) continue; // ์ด๋ฏธ ๋ฐฉ๋ฌธ
93 if (dist[u][v] == INF) continue;
94
95 int newMask = mask | (1 << v);
96 dp[newMask][v] = min(dp[newMask][v], dp[mask][u] + dist[u][v]);
97 }
98 }
99 }
100
101 // ๋ชจ๋ ๋์ ๋ฐฉ๋ฌธ ํ ์์์ ์ผ๋ก ๋ณต๊ท
102 int fullMask = (1 << n) - 1;
103 int result = INF;
104 for (int i = 0; i < n; i++) {
105 if (dp[fullMask][i] != INF && dist[i][0] != INF) {
106 result = min(result, dp[fullMask][i] + dist[i][0]);
107 }
108 }
109
110 return result;
111}
112
113// TSP ๊ฒฝ๋ก ๋ณต์
114pair<int, vector<int>> tspWithPath(int n, const vector<vector<int>>& dist) {
115 vector<vector<int>> dp(1 << n, vector<int>(n, INF));
116 vector<vector<int>> parent(1 << n, vector<int>(n, -1));
117
118 dp[1][0] = 0;
119
120 for (int mask = 1; mask < (1 << n); mask++) {
121 for (int u = 0; u < n; u++) {
122 if (!(mask & (1 << u))) continue;
123 if (dp[mask][u] == INF) continue;
124
125 for (int v = 0; v < n; v++) {
126 if (mask & (1 << v)) continue;
127 if (dist[u][v] == INF) continue;
128
129 int newMask = mask | (1 << v);
130 if (dp[mask][u] + dist[u][v] < dp[newMask][v]) {
131 dp[newMask][v] = dp[mask][u] + dist[u][v];
132 parent[newMask][v] = u;
133 }
134 }
135 }
136 }
137
138 // ์ต์ข
๊ฒฐ๊ณผ
139 int fullMask = (1 << n) - 1;
140 int result = INF;
141 int lastCity = -1;
142
143 for (int i = 0; i < n; i++) {
144 if (dp[fullMask][i] != INF && dist[i][0] != INF) {
145 if (dp[fullMask][i] + dist[i][0] < result) {
146 result = dp[fullMask][i] + dist[i][0];
147 lastCity = i;
148 }
149 }
150 }
151
152 // ๊ฒฝ๋ก ๋ณต์
153 vector<int> path;
154 int mask = fullMask;
155 int curr = lastCity;
156
157 while (curr != -1) {
158 path.push_back(curr);
159 int prev = parent[mask][curr];
160 mask ^= (1 << curr);
161 curr = prev;
162 }
163
164 reverse(path.begin(), path.end());
165 path.push_back(0); // ์์์ ์ผ๋ก ๋ณต๊ท
166
167 return {result, path};
168}
169
170// =============================================================================
171// 4. ์์
ํ ๋น ๋ฌธ์ (Assignment Problem)
172// =============================================================================
173
174int minCostAssignment(int n, const vector<vector<int>>& cost) {
175 // dp[mask]: mask์ ํด๋นํ๋ ์์
๋ค์ด ํ ๋น๋์์ ๋ ์ต์ ๋น์ฉ
176 vector<int> dp(1 << n, INF);
177 dp[0] = 0;
178
179 for (int mask = 0; mask < (1 << n); mask++) {
180 int person = __builtin_popcount(mask); // ํ์ฌ ํ ๋นํ ์ฌ๋
181 if (person >= n) continue;
182
183 for (int job = 0; job < n; job++) {
184 if (mask & (1 << job)) continue; // ์ด๋ฏธ ํ ๋น๋ ์์
185
186 int newMask = mask | (1 << job);
187 dp[newMask] = min(dp[newMask], dp[mask] + cost[person][job]);
188 }
189 }
190
191 return dp[(1 << n) - 1];
192}
193
194// =============================================================================
195// 5. ๋ถ๋ถ์งํฉ ํฉ (Subset Sum)
196// =============================================================================
197
198bool subsetSum(const vector<int>& nums, int target) {
199 int n = nums.size();
200
201 for (int mask = 0; mask < (1 << n); mask++) {
202 int sum = 0;
203 for (int i = 0; i < n; i++) {
204 if (mask & (1 << i)) {
205 sum += nums[i];
206 }
207 }
208 if (sum == target) return true;
209 }
210
211 return false;
212}
213
214// ์ต์ ํ: Meet in the Middle
215bool subsetSumMITM(const vector<int>& nums, int target) {
216 int n = nums.size();
217 int half = n / 2;
218
219 // ์์ชฝ ์ ๋ฐ์ ๋ชจ๋ ๋ถ๋ถ์งํฉ ํฉ
220 vector<int> leftSums;
221 for (int mask = 0; mask < (1 << half); mask++) {
222 int sum = 0;
223 for (int i = 0; i < half; i++) {
224 if (mask & (1 << i)) sum += nums[i];
225 }
226 leftSums.push_back(sum);
227 }
228 sort(leftSums.begin(), leftSums.end());
229
230 // ๋ค์ชฝ ์ ๋ฐ ํ์ธ
231 int rightHalf = n - half;
232 for (int mask = 0; mask < (1 << rightHalf); mask++) {
233 int sum = 0;
234 for (int i = 0; i < rightHalf; i++) {
235 if (mask & (1 << i)) sum += nums[half + i];
236 }
237
238 // target - sum์ด leftSums์ ์๋์ง ํ์ธ
239 if (binary_search(leftSums.begin(), leftSums.end(), target - sum)) {
240 return true;
241 }
242 }
243
244 return false;
245}
246
247// =============================================================================
248// 6. ํด๋ฐํด ๊ฒฝ๋ก
249// =============================================================================
250
251int countHamiltonianPaths(int n, const vector<vector<int>>& adj) {
252 // dp[mask][i]: mask ์งํฉ์ ๋ฐฉ๋ฌธํ๊ณ i์์ ๋๋๋ ๊ฒฝ๋ก ์
253 vector<vector<int>> dp(1 << n, vector<int>(n, 0));
254
255 // ์์์ ์ด๊ธฐํ
256 for (int i = 0; i < n; i++) {
257 dp[1 << i][i] = 1;
258 }
259
260 for (int mask = 1; mask < (1 << n); mask++) {
261 for (int u = 0; u < n; u++) {
262 if (!(mask & (1 << u))) continue;
263 if (dp[mask][u] == 0) continue;
264
265 for (int v : adj[u]) {
266 if (mask & (1 << v)) continue;
267
268 int newMask = mask | (1 << v);
269 dp[newMask][v] += dp[mask][u];
270 }
271 }
272 }
273
274 // ๋ชจ๋ ์ ์ ๋ฐฉ๋ฌธํ ๊ฒฝ๋ก ์
275 int fullMask = (1 << n) - 1;
276 int total = 0;
277 for (int i = 0; i < n; i++) {
278 total += dp[fullMask][i];
279 }
280
281 return total;
282}
283
284// =============================================================================
285// 7. SOS DP (Sum over Subsets)
286// =============================================================================
287
288void sosDP(vector<int>& dp, int n) {
289 // dp[mask]์ mask์ ๋ชจ๋ ๋ถ๋ถ์งํฉ์ ํฉ ์ ์ฅ
290 for (int i = 0; i < n; i++) {
291 for (int mask = 0; mask < (1 << n); mask++) {
292 if (mask & (1 << i)) {
293 dp[mask] += dp[mask ^ (1 << i)];
294 }
295 }
296 }
297}
298
299// =============================================================================
300// ํ
์คํธ
301// =============================================================================
302
303void printVector(const vector<int>& v) {
304 cout << "[";
305 for (size_t i = 0; i < v.size(); i++) {
306 cout << v[i];
307 if (i < v.size() - 1) cout << ", ";
308 }
309 cout << "]";
310}
311
312int main() {
313 cout << "============================================================" << endl;
314 cout << "๋นํธ๋ง์คํฌ DP ์์ " << endl;
315 cout << "============================================================" << endl;
316
317 // 1. ๋นํธ ์ฐ์ฐ ๊ธฐ์ด
318 bitOperations();
319
320 // 2. ๋ถ๋ถ์งํฉ ์ํ
321 enumerateSubsets(3);
322
323 // 3. TSP
324 cout << "\n[3] ์ธํ์ ๋ฌธ์ (TSP)" << endl;
325 vector<vector<int>> dist = {
326 {0, 10, 15, 20},
327 {10, 0, 35, 25},
328 {15, 35, 0, 30},
329 {20, 25, 30, 0}
330 };
331 cout << " ๊ฑฐ๋ฆฌ ํ๋ ฌ: 4x4" << endl;
332 cout << " ์ต์ ๋น์ฉ: " << tsp(4, dist) << endl;
333
334 auto [cost, path] = tspWithPath(4, dist);
335 cout << " ๊ฒฝ๋ก: ";
336 printVector(path);
337 cout << endl;
338
339 // 4. ์์
ํ ๋น
340 cout << "\n[4] ์์
ํ ๋น ๋ฌธ์ " << endl;
341 vector<vector<int>> costMatrix = {
342 {9, 2, 7, 8},
343 {6, 4, 3, 7},
344 {5, 8, 1, 8},
345 {7, 6, 9, 4}
346 };
347 cout << " ๋น์ฉ ํ๋ ฌ: 4x4" << endl;
348 cout << " ์ต์ ๋น์ฉ: " << minCostAssignment(4, costMatrix) << endl;
349
350 // 5. ๋ถ๋ถ์งํฉ ํฉ
351 cout << "\n[5] ๋ถ๋ถ์งํฉ ํฉ" << endl;
352 vector<int> nums = {3, 34, 4, 12, 5, 2};
353 cout << " ๋ฐฐ์ด: [3, 34, 4, 12, 5, 2]" << endl;
354 cout << " ํฉ 9 ์กด์ฌ: " << (subsetSum(nums, 9) ? "์" : "์๋์ค") << endl;
355 cout << " ํฉ 30 ์กด์ฌ: " << (subsetSum(nums, 30) ? "์" : "์๋์ค") << endl;
356
357 // 6. SOS DP
358 cout << "\n[6] SOS DP" << endl;
359 vector<int> sos = {1, 2, 3, 4, 5, 6, 7, 8}; // 2^3 = 8
360 cout << " ์ด๊ธฐ: ";
361 printVector(sos);
362 cout << endl;
363 sosDP(sos, 3);
364 cout << " SOS: ";
365 printVector(sos);
366 cout << endl;
367
368 // 7. ๋ณต์ก๋ ์์ฝ
369 cout << "\n[7] ๋ณต์ก๋ ์์ฝ" << endl;
370 cout << " | ๋ฌธ์ | ์๊ฐ๋ณต์ก๋ | ๊ณต๊ฐ๋ณต์ก๋ |" << endl;
371 cout << " |--------------------|---------------|------------|" << endl;
372 cout << " | TSP | O(nยฒ ร 2^n) | O(n ร 2^n) |" << endl;
373 cout << " | ์์
ํ ๋น | O(n ร 2^n) | O(2^n) |" << endl;
374 cout << " | ๋ถ๋ถ์งํฉ ํฉ | O(2^n) | O(1) |" << endl;
375 cout << " | Meet in the Middle | O(n ร 2^(n/2))| O(2^(n/2)) |" << endl;
376 cout << " | SOS DP | O(n ร 2^n) | O(2^n) |" << endl;
377
378 // 8. ๋นํธ๋ง์คํฌ ํ
379 cout << "\n[8] ๋นํธ๋ง์คํฌ ํ" << endl;
380 cout << " - n โค 20: ๋นํธ๋ง์คํฌ DP ๊ณ ๋ ค" << endl;
381 cout << " - n โค 25: Meet in the Middle ๊ณ ๋ ค" << endl;
382 cout << " - __builtin_popcount(x): 1์ ๊ฐ์ (GCC)" << endl;
383 cout << " - x & -x: ์ตํ์ 1๋นํธ" << endl;
384 cout << " - x & (x-1): ์ตํ์ 1๋นํธ ์ ๊ฑฐ" << endl;
385
386 cout << "\n============================================================" << endl;
387
388 return 0;
389}