학교에서 진행하는 알고리즘 수업을 정리해보려고 한다.
#include <stdio.h>
void main() {
int arr[10] = { 1,2,3,4,15,6,7,8,9,11 };
int tmp = 0;
for(int i = 0; i < 10; i++) {
if (arr[i] > tmp ) {
tmp = arr[i];
}
}
printf("Max is %d\n", tmp);
}
#include <stdio.h>
void main() {
int arr[10] = { 1,2,3,4,15,6,7,8,9,11 };
int num;
int found = 0;
printf("찾고 싶은 숫자를 입력하세요: ");
scanf_s("%d", &num);
for (int i = 0; i < 10; i++) {
if (arr[i] == num) {
printf("배열에 %d가 있습니다. 그 숫자의 위치는 배열의 %d번째에 있습니다.\n", num, i + 1);
found = 1;
break;
}
}
if (!found) {
printf("%d는 배열에 없습니다.\n", num);
}
}
#include <stdio.h>
void main() {
int coin = 0;
int rest = 730;
while (rest > 0) {
if (rest >= 500) {
rest -= 500;
coin++;
}
else if (rest >= 100) {
rest -= 100;
coin++;
}
else if (rest >= 50) {
rest -= 50;
coin++;
}
else if (rest >= 10) {
rest -= 10;
coin++;
}
else {
break;
}
}
printf("필요한 동전의 개수: %d\n", coin);
}
#include <stdio.h>
#define MAX 10
int graph[MAX][MAX];
int degree[MAX];
int n;
void initGraph() {
n = 4;
graph[1][2] = graph[2][1] = 1;
graph[2][3] = graph[3][2] = 1;
graph[3][4] = graph[4][3] = 1;
graph[4][1] = graph[1][4] = 1;
}
void calcDegree() {
for (int i = 1; i <= n; i++) {
degree[i] = 0;
for (int j = 1; j <= n; j++) {
if (graph[i][j] == 1)
degree[i]++;
}
}
}
void checkEuler() {
int oddCount = 0;
for (int i = 1; i <= n; i++) {
if (degree[i] % 2 == 1)
oddCount++;
}
if (oddCount == 0)
printf("Eulerian Circuit 가능\n");
else if (oddCount == 2)
printf("Eulerian Path 가능\n");
else
printf("한붓그리기 불가능\n");
}
void dfs(int u) {
for (int v = 1; v <= n; v++) {
if (graph[u][v]) {
graph[u][v] = graph[v][u] = 0;
dfs(v);
}
}
printf("%d ", u);
}
void main() {
initGraph();
calcDegree();
checkEuler();
printf("한붓그리기 경로 (역순): ");
dfs(1);
printf("\n");
}
#include <stdio.h>
#define N 7
int maze[N][N] = {
{1,1,1,1,1,1,1},
{1,0,0,0,1,0,1},
{1,0,1,0,1,0,1},
{1,0,1,0,0,0,1},
{1,0,1,1,1,0,1},
{1,0,0,0,0,0,1},
{1,1,1,1,1,1,1}
};
// 북, 동, 남, 서
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
// 오른손 법칙 미로 탐색
void rightHandMaze(int startX, int startY, int endX, int endY) {
int x = startX, y = startY;
int dir = 1; // 시작 시 오른쪽(동쪽)을 바라본다고 가정
int step = 0;
while (1) {
printf("(%d, %d)\n", x, y);
if (x == endX && y == endY) {
printf("출구 도착! 총 %d걸음\n", step);
break;
}
// 오른쪽 방향
int rightDir = (dir + 1) % 4;
int rightX = x + dx[rightDir];
int rightY = y + dy[rightDir];
if (maze[rightX][rightY] == 0) {
// 오른쪽이 길이면 오른쪽으로 회전 후 전진
dir = rightDir;
x += dx[dir];
y += dy[dir];
}
else if (maze[x + dx[dir]][y + dy[dir]] == 0) {
// 정면이 길이면 그대로 전진
x += dx[dir];
y += dy[dir];
}
else {
// 둘 다 벽이면 왼쪽으로 회전
dir = (dir + 3) % 4;
}
step++;
if (step > 1000) { // 무한루프 방지
printf("출구를 찾지 못했습니다.\n");
break;
}
}
}
int main() {
rightHandMaze(1, 1, 5, 5);
return 0;
}
#include <stdio.h>
int main(void) {
int N;
printf("술단지 개수 N을 입력하세요: ");
if (scanf_s("%d", &N) != 1 || N <= 0) {
printf("유효한 양의 정수를 입력하세요.\n");
return 0;
}
// 최소 신하 수 k = ceil(log2(N))을 반복문으로 계산
int k = 0;
int cap = 1; // 2^k
while (cap < N) { cap <<= 1; k++; }
printf("\n[요약]\n");
printf("- 술단지 개수 N = %d\n", N);
printf("- 최소 신하 수 k = %d (2^%d = %d >= %d)\n", k, k, cap, N);
if (k == 0) {
// N == 1인 경우: 신하가 필요 없음
printf("- 술단지가 1개뿐이므로 신하가 필요 없습니다. 그 1개가 독일 수밖에 없습니다.\n");
return 0;
}
// 신하별 할당표 출력
// 신하 s(0=LSB)는 (b-1)의 s번째 비트가 1인 배럴을 마신다.
printf("\n[신하별 할당표]\n");
for (int s = 0; s < k; s++) {
printf("신하 %d (비트 %d): ", s, s);
int first = 1;
for (int b = 1; b <= N; b++) {
if (((b - 1) >> s) & 1) {
if (!first) printf(", ");
printf("%d", b);
first = 0;
}
}
if (first) printf("(해당 없음)");
printf("\n");
}
return 0;
}
순차 탐색 ( Sequential Search ) : 주어진 순서에 따라 차례로 탐색
이진 탐색 ( Binary Search ) : 정렬된 데이터에 대해서 중간에 있는 데이터를 비교하여 그 결과에 따라 같으면 탐색을 마치고 , 다르면 작은 쪽 또는 큰 쪽을 같은 방식으로 탐색
동전 거스름돈 문제에서 항상 욕심 내어 가장 큰 동전을 선택 → 그리디 알고리즘
한붓그리기 문제는 오일러 서킷 ( Euler Circuit ) 문제와 같다. 알고리즘의 핵심은 현재 점에서 사이클이 존재하면 진행.
가짜 동전 찾기에서 동전 더미를 반으로 분할하여 저울에 달고, 가짜 동전이 있는 더미를 계속해서 반으로 나누어 저울에 단다. ← 분할 정복 ( Divide And Conquer ) 알고리즘
독이든 술 단지 문제는 2진수를 활용 ( Binary Tree ) 하여 해를 찾는다.