1/*
2 * ๋นํธ๋ง์คํฌ DP (Bitmask DP)
3 * TSP, Set Partition, Subset DP
4 *
5 * ๋นํธ ์ฐ์ฐ์ ํ์ฉํ ์งํฉ ์ํ ํํ๊ณผ DP์
๋๋ค.
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <limits.h>
11
12#define INF INT_MAX
13#define MIN(a, b) ((a) < (b) ? (a) : (b))
14#define MAX(a, b) ((a) > (b) ? (a) : (b))
15
16/* =============================================================================
17 * 1. ๋นํธ ์ฐ์ฐ ๊ธฐ์ด
18 * ============================================================================= */
19
20void print_binary(int n, int bits) {
21 for (int i = bits - 1; i >= 0; i--) {
22 printf("%d", (n >> i) & 1);
23 }
24}
25
26int count_bits(int n) {
27 int count = 0;
28 while (n) {
29 count += n & 1;
30 n >>= 1;
31 }
32 return count;
33}
34
35/* =============================================================================
36 * 2. TSP (Traveling Salesman Problem)
37 * ============================================================================= */
38
39int tsp(int** dist, int n) {
40 int full_mask = (1 << n) - 1;
41 int** dp = malloc((1 << n) * sizeof(int*));
42 for (int i = 0; i < (1 << n); i++) {
43 dp[i] = malloc(n * sizeof(int));
44 for (int j = 0; j < n; j++) dp[i][j] = INF;
45 }
46
47 dp[1][0] = 0; /* ์์์ 0 ๋ฐฉ๋ฌธ */
48
49 for (int mask = 1; mask <= full_mask; mask++) {
50 for (int last = 0; last < n; last++) {
51 if (!(mask & (1 << last))) continue;
52 if (dp[mask][last] == INF) continue;
53
54 for (int next = 0; next < n; next++) {
55 if (mask & (1 << next)) continue;
56 if (dist[last][next] == 0) continue;
57
58 int new_mask = mask | (1 << next);
59 int new_cost = dp[mask][last] + dist[last][next];
60 if (new_cost < dp[new_mask][next]) {
61 dp[new_mask][next] = new_cost;
62 }
63 }
64 }
65 }
66
67 int result = INF;
68 for (int last = 1; last < n; last++) {
69 if (dp[full_mask][last] != INF && dist[last][0] > 0) {
70 int cost = dp[full_mask][last] + dist[last][0];
71 if (cost < result) result = cost;
72 }
73 }
74
75 for (int i = 0; i < (1 << n); i++) free(dp[i]);
76 free(dp);
77 return result;
78}
79
80/* =============================================================================
81 * 3. ๋ถ๋ถ์งํฉ ํฉ
82 * ============================================================================= */
83
84int subset_sum_exists(int arr[], int n, int target) {
85 int full = 1 << n;
86 for (int mask = 0; mask < full; mask++) {
87 int sum = 0;
88 for (int i = 0; i < n; i++) {
89 if (mask & (1 << i)) sum += arr[i];
90 }
91 if (sum == target) return 1;
92 }
93 return 0;
94}
95
96/* =============================================================================
97 * 4. ์งํฉ ๋ถํ (๋ ๋ถ๋ถ์งํฉ ํฉ ์ฐจ์ด ์ต์)
98 * ============================================================================= */
99
100int min_partition_diff(int arr[], int n) {
101 int total = 0;
102 for (int i = 0; i < n; i++) total += arr[i];
103
104 int full = 1 << n;
105 int min_diff = total;
106
107 for (int mask = 0; mask < full; mask++) {
108 int sum = 0;
109 for (int i = 0; i < n; i++) {
110 if (mask & (1 << i)) sum += arr[i];
111 }
112 int diff = abs(total - 2 * sum);
113 if (diff < min_diff) min_diff = diff;
114 }
115
116 return min_diff;
117}
118
119/* =============================================================================
120 * 5. ํ ๋น ๋ฌธ์ (Assignment Problem)
121 * ============================================================================= */
122
123int assignment_problem(int** cost, int n) {
124 int* dp = malloc((1 << n) * sizeof(int));
125 for (int i = 0; i < (1 << n); i++) dp[i] = INF;
126 dp[0] = 0;
127
128 for (int mask = 0; mask < (1 << n); mask++) {
129 if (dp[mask] == INF) continue;
130 int person = count_bits(mask);
131 if (person >= n) continue;
132
133 for (int task = 0; task < n; task++) {
134 if (mask & (1 << task)) continue;
135 int new_mask = mask | (1 << task);
136 int new_cost = dp[mask] + cost[person][task];
137 if (new_cost < dp[new_mask]) dp[new_mask] = new_cost;
138 }
139 }
140
141 int result = dp[(1 << n) - 1];
142 free(dp);
143 return result;
144}
145
146/* =============================================================================
147 * 6. ํด๋ฐํด ๊ฒฝ๋ก ๊ฐ์
148 * ============================================================================= */
149
150int hamilton_paths(int** adj, int n, int start) {
151 int** dp = malloc((1 << n) * sizeof(int*));
152 for (int i = 0; i < (1 << n); i++) {
153 dp[i] = calloc(n, sizeof(int));
154 }
155
156 dp[1 << start][start] = 1;
157
158 for (int mask = 0; mask < (1 << n); mask++) {
159 for (int last = 0; last < n; last++) {
160 if (!(mask & (1 << last))) continue;
161 if (dp[mask][last] == 0) continue;
162
163 for (int next = 0; next < n; next++) {
164 if (mask & (1 << next)) continue;
165 if (!adj[last][next]) continue;
166
167 int new_mask = mask | (1 << next);
168 dp[new_mask][next] += dp[mask][last];
169 }
170 }
171 }
172
173 int full = (1 << n) - 1;
174 int total = 0;
175 for (int i = 0; i < n; i++) total += dp[full][i];
176
177 for (int i = 0; i < (1 << n); i++) free(dp[i]);
178 free(dp);
179 return total;
180}
181
182/* =============================================================================
183 * 7. SOS DP (Sum over Subsets)
184 * ============================================================================= */
185
186void sos_dp(int f[], int n) {
187 int full = 1 << n;
188 for (int i = 0; i < n; i++) {
189 for (int mask = 0; mask < full; mask++) {
190 if (mask & (1 << i)) {
191 f[mask] += f[mask ^ (1 << i)];
192 }
193 }
194 }
195}
196
197/* =============================================================================
198 * ํ
์คํธ
199 * ============================================================================= */
200
201int main(void) {
202 printf("============================================================\n");
203 printf("๋นํธ๋ง์คํฌ DP ์์ \n");
204 printf("============================================================\n");
205
206 /* 1. ๋นํธ ์ฐ์ฐ */
207 printf("\n[1] ๋นํธ ์ฐ์ฐ ๊ธฐ์ด\n");
208 printf(" 5 = "); print_binary(5, 4); printf("\n");
209 printf(" 5 | 2 = %d\n", 5 | 2);
210 printf(" 5 & 2 = %d\n", 5 & 2);
211 printf(" 5 ^ 2 = %d\n", 5 ^ 2);
212 printf(" count_bits(13) = %d\n", count_bits(13));
213
214 /* 2. TSP */
215 printf("\n[2] TSP (์ธํ์ ๋ฌธ์ )\n");
216 int** dist = malloc(4 * sizeof(int*));
217 for (int i = 0; i < 4; i++) dist[i] = malloc(4 * sizeof(int));
218 int d[4][4] = {{0, 10, 15, 20}, {10, 0, 35, 25}, {15, 35, 0, 30}, {20, 25, 30, 0}};
219 for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) dist[i][j] = d[i][j];
220 printf(" ์ต์ ๋น์ฉ: %d\n", tsp(dist, 4));
221 for (int i = 0; i < 4; i++) free(dist[i]);
222 free(dist);
223
224 /* 3. ๋ถ๋ถ์งํฉ ํฉ */
225 printf("\n[3] ๋ถ๋ถ์งํฉ ํฉ\n");
226 int arr[] = {3, 34, 4, 12, 5, 2};
227 printf(" ๋ฐฐ์ด: [3,34,4,12,5,2]\n");
228 printf(" ํฉ 9 ์กด์ฌ: %s\n", subset_sum_exists(arr, 6, 9) ? "์" : "์๋์ค");
229 printf(" ํฉ 30 ์กด์ฌ: %s\n", subset_sum_exists(arr, 6, 30) ? "์" : "์๋์ค");
230
231 /* 4. ์งํฉ ๋ถํ */
232 printf("\n[4] ์งํฉ ๋ถํ ์ต์ ์ฐจ์ด\n");
233 int arr2[] = {1, 6, 11, 5};
234 printf(" [1,6,11,5]: ์ต์ ์ฐจ์ด = %d\n", min_partition_diff(arr2, 4));
235
236 /* 5. ํ ๋น ๋ฌธ์ */
237 printf("\n[5] ํ ๋น ๋ฌธ์ \n");
238 int** cost = malloc(3 * sizeof(int*));
239 for (int i = 0; i < 3; i++) cost[i] = malloc(3 * sizeof(int));
240 int c[3][3] = {{9, 2, 7}, {6, 4, 3}, {5, 8, 1}};
241 for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) cost[i][j] = c[i][j];
242 printf(" ๋น์ฉ ํ๋ ฌ:\n");
243 for (int i = 0; i < 3; i++) {
244 printf(" ");
245 for (int j = 0; j < 3; j++) printf("%d ", c[i][j]);
246 printf("\n");
247 }
248 printf(" ์ต์ ๋น์ฉ: %d\n", assignment_problem(cost, 3));
249 for (int i = 0; i < 3; i++) free(cost[i]);
250 free(cost);
251
252 /* 6. ๋ณต์ก๋ */
253 printf("\n[6] ๋นํธ๋ง์คํฌ DP ๋ณต์ก๋\n");
254 printf(" TSP: O(nยฒ ร 2^n)\n");
255 printf(" ๋ถ๋ถ์งํฉ ํฉ: O(n ร 2^n)\n");
256 printf(" ํ ๋น ๋ฌธ์ : O(n ร 2^n)\n");
257 printf(" SOS DP: O(n ร 2^n)\n");
258
259 printf("\n============================================================\n");
260
261 return 0;
262}