1/*
2 * ์ค์ ๋ฌธ์ ํ์ด (Practice Problems)
3 * ์ข
ํฉ ๋ฌธ์ (๋ค์ํ ์๊ณ ๋ฆฌ์ฆ ์กฐํฉ)
4 *
5 * ์ฝ๋ฉ ํ
์คํธ์์ ์์ฃผ ๋์ค๋ ์ ํ๋ค์
๋๋ค.
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <stdbool.h>
12#include <limits.h>
13
14#define MAX_N 100001
15#define INF INT_MAX
16
17typedef long long ll;
18
19/* =============================================================================
20 * 1. ๋ถ๋ถ ๋ฐฐ์ด ํฉ (ํฌ ํฌ์ธํฐ)
21 * ============================================================================= */
22
23/* ํฉ์ด target ์ด์์ธ ์ต์ ๊ธธ์ด ๋ถ๋ถ ๋ฐฐ์ด */
24int min_subarray_sum(int arr[], int n, int target) {
25 int left = 0;
26 int sum = 0;
27 int min_len = n + 1;
28
29 for (int right = 0; right < n; right++) {
30 sum += arr[right];
31
32 while (sum >= target) {
33 int len = right - left + 1;
34 if (len < min_len) min_len = len;
35 sum -= arr[left++];
36 }
37 }
38
39 return (min_len == n + 1) ? 0 : min_len;
40}
41
42/* =============================================================================
43 * 2. ์์
์ค์ผ์ค๋ง (Greedy + Heap)
44 * ============================================================================= */
45
46typedef struct {
47 int deadline;
48 int profit;
49} Job;
50
51int compare_jobs(const void* a, const void* b) {
52 return ((Job*)b)->profit - ((Job*)a)->profit;
53}
54
55int job_scheduling(Job jobs[], int n) {
56 qsort(jobs, n, sizeof(Job), compare_jobs);
57
58 int max_deadline = 0;
59 for (int i = 0; i < n; i++) {
60 if (jobs[i].deadline > max_deadline)
61 max_deadline = jobs[i].deadline;
62 }
63
64 int* slot = malloc((max_deadline + 1) * sizeof(int));
65 memset(slot, -1, (max_deadline + 1) * sizeof(int));
66
67 int total_profit = 0;
68 int job_count = 0;
69
70 for (int i = 0; i < n; i++) {
71 for (int j = jobs[i].deadline; j >= 1; j--) {
72 if (slot[j] == -1) {
73 slot[j] = i;
74 total_profit += jobs[i].profit;
75 job_count++;
76 break;
77 }
78 }
79 }
80
81 free(slot);
82 return total_profit;
83}
84
85/* =============================================================================
86 * 3. ์ต์ ํ์์ค ์ (์ด๋ฒคํธ ์ ๋ ฌ)
87 * ============================================================================= */
88
89typedef struct {
90 int time;
91 int type; /* 1: ์์, -1: ์ข
๋ฃ */
92} Event;
93
94int compare_events(const void* a, const void* b) {
95 Event* e1 = (Event*)a;
96 Event* e2 = (Event*)b;
97 if (e1->time != e2->time)
98 return e1->time - e2->time;
99 return e1->type - e2->type; /* ์ข
๋ฃ๊ฐ ๋จผ์ */
100}
101
102int min_meeting_rooms(int start[], int end[], int n) {
103 Event* events = malloc(2 * n * sizeof(Event));
104
105 for (int i = 0; i < n; i++) {
106 events[2 * i] = (Event){start[i], 1};
107 events[2 * i + 1] = (Event){end[i], -1};
108 }
109
110 qsort(events, 2 * n, sizeof(Event), compare_events);
111
112 int rooms = 0, max_rooms = 0;
113 for (int i = 0; i < 2 * n; i++) {
114 rooms += events[i].type;
115 if (rooms > max_rooms) max_rooms = rooms;
116 }
117
118 free(events);
119 return max_rooms;
120}
121
122/* =============================================================================
123 * 4. ํฐ๋ฆฐ๋๋กฌ ๋ณํ (DP)
124 * ============================================================================= */
125
126int min_palindrome_insertions(char* s) {
127 int n = strlen(s);
128 int** dp = malloc(n * sizeof(int*));
129 for (int i = 0; i < n; i++) {
130 dp[i] = calloc(n, sizeof(int));
131 }
132
133 for (int len = 2; len <= n; len++) {
134 for (int i = 0; i + len - 1 < n; i++) {
135 int j = i + len - 1;
136 if (s[i] == s[j]) {
137 dp[i][j] = dp[i + 1][j - 1];
138 } else {
139 int v1 = dp[i + 1][j];
140 int v2 = dp[i][j - 1];
141 dp[i][j] = 1 + (v1 < v2 ? v1 : v2);
142 }
143 }
144 }
145
146 int result = dp[0][n - 1];
147 for (int i = 0; i < n; i++) free(dp[i]);
148 free(dp);
149 return result;
150}
151
152/* =============================================================================
153 * 5. ์ฌ์ ๊ฐ์ (DFS/BFS)
154 * ============================================================================= */
155
156int dx[] = {-1, 1, 0, 0};
157int dy[] = {0, 0, -1, 1};
158
159void dfs_island(int** grid, int rows, int cols, int i, int j, bool** visited) {
160 if (i < 0 || i >= rows || j < 0 || j >= cols) return;
161 if (visited[i][j] || grid[i][j] == 0) return;
162
163 visited[i][j] = true;
164 for (int d = 0; d < 4; d++) {
165 dfs_island(grid, rows, cols, i + dx[d], j + dy[d], visited);
166 }
167}
168
169int count_islands(int** grid, int rows, int cols) {
170 bool** visited = malloc(rows * sizeof(bool*));
171 for (int i = 0; i < rows; i++) {
172 visited[i] = calloc(cols, sizeof(bool));
173 }
174
175 int count = 0;
176 for (int i = 0; i < rows; i++) {
177 for (int j = 0; j < cols; j++) {
178 if (grid[i][j] == 1 && !visited[i][j]) {
179 dfs_island(grid, rows, cols, i, j, visited);
180 count++;
181 }
182 }
183 }
184
185 for (int i = 0; i < rows; i++) free(visited[i]);
186 free(visited);
187 return count;
188}
189
190/* =============================================================================
191 * 6. Union-Find ์์ฉ (์ค๋ณต ์ฐ๊ฒฐ)
192 * ============================================================================= */
193
194int uf_parent[MAX_N];
195int uf_rank_arr[MAX_N];
196
197void uf_init(int n) {
198 for (int i = 0; i < n; i++) {
199 uf_parent[i] = i;
200 uf_rank_arr[i] = 0;
201 }
202}
203
204int uf_find(int x) {
205 if (uf_parent[x] != x)
206 uf_parent[x] = uf_find(uf_parent[x]);
207 return uf_parent[x];
208}
209
210bool uf_union(int x, int y) {
211 int px = uf_find(x);
212 int py = uf_find(y);
213 if (px == py) return false;
214
215 if (uf_rank_arr[px] < uf_rank_arr[py]) {
216 uf_parent[px] = py;
217 } else if (uf_rank_arr[px] > uf_rank_arr[py]) {
218 uf_parent[py] = px;
219 } else {
220 uf_parent[py] = px;
221 uf_rank_arr[px]++;
222 }
223 return true;
224}
225
226/* ์ค๋ณต ์ฐ๊ฒฐ ์ฐพ๊ธฐ */
227int* find_redundant_connection(int edges[][2], int n) {
228 uf_init(n + 1);
229 static int result[2];
230
231 for (int i = 0; i < n; i++) {
232 if (!uf_union(edges[i][0], edges[i][1])) {
233 result[0] = edges[i][0];
234 result[1] = edges[i][1];
235 return result;
236 }
237 }
238
239 result[0] = -1;
240 result[1] = -1;
241 return result;
242}
243
244/* =============================================================================
245 * 7. LIS (Longest Increasing Subsequence)
246 * ============================================================================= */
247
248int lower_bound(int arr[], int n, int target) {
249 int lo = 0, hi = n;
250 while (lo < hi) {
251 int mid = (lo + hi) / 2;
252 if (arr[mid] < target) lo = mid + 1;
253 else hi = mid;
254 }
255 return lo;
256}
257
258int lis_length(int arr[], int n) {
259 int* tails = malloc(n * sizeof(int));
260 int len = 0;
261
262 for (int i = 0; i < n; i++) {
263 int pos = lower_bound(tails, len, arr[i]);
264 tails[pos] = arr[i];
265 if (pos == len) len++;
266 }
267
268 free(tails);
269 return len;
270}
271
272/* =============================================================================
273 * 8. ์ค๋์ฟ (๋ฐฑํธ๋ํน)
274 * ============================================================================= */
275
276bool is_valid_sudoku(int board[9][9], int row, int col, int num) {
277 /* ํ ๊ฒ์ฌ */
278 for (int j = 0; j < 9; j++) {
279 if (board[row][j] == num) return false;
280 }
281
282 /* ์ด ๊ฒ์ฌ */
283 for (int i = 0; i < 9; i++) {
284 if (board[i][col] == num) return false;
285 }
286
287 /* 3x3 ๋ฐ์ค ๊ฒ์ฌ */
288 int box_row = (row / 3) * 3;
289 int box_col = (col / 3) * 3;
290 for (int i = 0; i < 3; i++) {
291 for (int j = 0; j < 3; j++) {
292 if (board[box_row + i][box_col + j] == num) return false;
293 }
294 }
295
296 return true;
297}
298
299bool solve_sudoku(int board[9][9]) {
300 for (int i = 0; i < 9; i++) {
301 for (int j = 0; j < 9; j++) {
302 if (board[i][j] == 0) {
303 for (int num = 1; num <= 9; num++) {
304 if (is_valid_sudoku(board, i, j, num)) {
305 board[i][j] = num;
306 if (solve_sudoku(board)) return true;
307 board[i][j] = 0;
308 }
309 }
310 return false;
311 }
312 }
313 }
314 return true;
315}
316
317/* =============================================================================
318 * 9. ์ด๋ถ ํ์ ์์ฉ (ํ๋ผ๋ฉํธ๋ฆญ ์์น)
319 * ============================================================================= */
320
321/* ์ต๋ ์ด๋ฐ ํ์๊ฐ days ์ดํ๊ฐ ๋๋๋ก ํ๋ ์ต์ ์ฉ๋ */
322bool can_ship(int weights[], int n, int capacity, int days) {
323 int current = 0;
324 int day_count = 1;
325
326 for (int i = 0; i < n; i++) {
327 if (weights[i] > capacity) return false;
328 if (current + weights[i] > capacity) {
329 day_count++;
330 current = weights[i];
331 } else {
332 current += weights[i];
333 }
334 }
335
336 return day_count <= days;
337}
338
339int ship_within_days(int weights[], int n, int days) {
340 int max_weight = 0, total = 0;
341 for (int i = 0; i < n; i++) {
342 if (weights[i] > max_weight) max_weight = weights[i];
343 total += weights[i];
344 }
345
346 int lo = max_weight, hi = total;
347 while (lo < hi) {
348 int mid = (lo + hi) / 2;
349 if (can_ship(weights, n, mid, days)) {
350 hi = mid;
351 } else {
352 lo = mid + 1;
353 }
354 }
355
356 return lo;
357}
358
359/* =============================================================================
360 * ํ
์คํธ
361 * ============================================================================= */
362
363int main(void) {
364 printf("============================================================\n");
365 printf("์ค์ ๋ฌธ์ ํ์ด ์์ \n");
366 printf("============================================================\n");
367
368 /* 1. ๋ถ๋ถ ๋ฐฐ์ด ํฉ */
369 printf("\n[1] ๋ถ๋ถ ๋ฐฐ์ด ํฉ (ํฌ ํฌ์ธํฐ)\n");
370 int arr1[] = {2, 3, 1, 2, 4, 3};
371 printf(" ๋ฐฐ์ด: [2, 3, 1, 2, 4, 3], target = 7\n");
372 printf(" ์ต์ ๊ธธ์ด: %d\n", min_subarray_sum(arr1, 6, 7));
373
374 /* 2. ์์
์ค์ผ์ค๋ง */
375 printf("\n[2] ์์
์ค์ผ์ค๋ง (Greedy)\n");
376 Job jobs[] = {{4, 20}, {1, 10}, {1, 40}, {1, 30}};
377 printf(" ์์
: {๋ง๊ฐ:4,์ด์ต:20}, {1,10}, {1,40}, {1,30}\n");
378 printf(" ์ต๋ ์ด์ต: %d\n", job_scheduling(jobs, 4));
379
380 /* 3. ์ต์ ํ์์ค */
381 printf("\n[3] ์ต์ ํ์์ค ์\n");
382 int start[] = {0, 5, 15};
383 int end[] = {30, 10, 20};
384 printf(" ํ์: [0-30], [5-10], [15-20]\n");
385 printf(" ์ต์ ํ์์ค: %d\n", min_meeting_rooms(start, end, 3));
386
387 /* 4. ํฐ๋ฆฐ๋๋กฌ ๋ณํ */
388 printf("\n[4] ํฐ๋ฆฐ๋๋กฌ ๋ณํ\n");
389 printf(" ๋ฌธ์์ด: \"abcde\"\n");
390 printf(" ์ต์ ์ฝ์
: %d\n", min_palindrome_insertions("abcde"));
391
392 /* 5. ์ฌ์ ๊ฐ์ */
393 printf("\n[5] ์ฌ์ ๊ฐ์\n");
394 int grid_data[4][4] = {
395 {1, 1, 0, 0},
396 {1, 0, 0, 0},
397 {0, 0, 1, 0},
398 {0, 0, 0, 1}
399 };
400 int** grid = malloc(4 * sizeof(int*));
401 for (int i = 0; i < 4; i++) {
402 grid[i] = malloc(4 * sizeof(int));
403 for (int j = 0; j < 4; j++) grid[i][j] = grid_data[i][j];
404 }
405 printf(" ๊ทธ๋ฆฌ๋:\n");
406 for (int i = 0; i < 4; i++) {
407 printf(" ");
408 for (int j = 0; j < 4; j++) printf("%d ", grid[i][j]);
409 printf("\n");
410 }
411 printf(" ์ฌ์ ๊ฐ์: %d\n", count_islands(grid, 4, 4));
412 for (int i = 0; i < 4; i++) free(grid[i]);
413 free(grid);
414
415 /* 6. ์ค๋ณต ์ฐ๊ฒฐ */
416 printf("\n[6] ์ค๋ณต ์ฐ๊ฒฐ ์ฐพ๊ธฐ (Union-Find)\n");
417 int edges[][2] = {{1, 2}, {1, 3}, {2, 3}};
418 int* redundant = find_redundant_connection(edges, 3);
419 printf(" ๊ฐ์ : (1,2), (1,3), (2,3)\n");
420 printf(" ์ค๋ณต ์ฐ๊ฒฐ: (%d, %d)\n", redundant[0], redundant[1]);
421
422 /* 7. LIS */
423 printf("\n[7] ์ต์ฅ ์ฆ๊ฐ ๋ถ๋ถ์์ด (LIS)\n");
424 int arr2[] = {10, 9, 2, 5, 3, 7, 101, 18};
425 printf(" ๋ฐฐ์ด: [10, 9, 2, 5, 3, 7, 101, 18]\n");
426 printf(" LIS ๊ธธ์ด: %d\n", lis_length(arr2, 8));
427
428 /* 8. ์ด๋ถ ํ์ ์์ฉ */
429 printf("\n[8] ์ด๋ถ ํ์ ์์ฉ (๋ฐฐ์ก)\n");
430 int weights[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
431 printf(" ๋ฌผ๊ฑด ๋ฌด๊ฒ: [1-10]\n");
432 printf(" 5์ผ ๋ด ๋ฐฐ์ก ์ต์ ์ฉ๋: %d\n", ship_within_days(weights, 10, 5));
433
434 /* 9. ๋ฌธ์ ํ์ด ์ ๋ต */
435 printf("\n[9] ๋ฌธ์ ํ์ด ์ ๋ต\n");
436 printf(" 1. ๋ฌธ์ ์ดํด: ์
๋ ฅ/์ถ๋ ฅ, ์ ์ฝ ์กฐ๊ฑด ํ์ธ\n");
437 printf(" 2. ์์ ๋ถ์: ์์ผ๋ก ํ์ด๋ณด๊ธฐ\n");
438 printf(" 3. ์๊ณ ๋ฆฌ์ฆ ์ ํ:\n");
439 printf(" - N โค 20: ์์ ํ์, ๋นํธ๋ง์คํฌ\n");
440 printf(" - N โค 10^3: O(Nยฒ) DP, ๋ธ๋ฃจํธํฌ์ค\n");
441 printf(" - N โค 10^5: O(N log N) ์ ๋ ฌ, ์ด๋ถํ์\n");
442 printf(" - N โค 10^7: O(N) ํฌ ํฌ์ธํฐ, ํด์\n");
443 printf(" 4. ๊ตฌํ ๋ฐ ํ
์คํธ\n");
444 printf(" 5. ์ฃ์ง ์ผ์ด์ค ํ์ธ\n");
445
446 printf("\n============================================================\n");
447
448 return 0;
449}