Skip to content

[이준희-14주차 알고리즘 스터디] #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: junhee325/week14
Choose a base branch
from

Conversation

JHLEE325
Copy link
Contributor

🚀 싸피 15반 알고리즘 스터디 14주차 [이준희]

📌 문제 풀이 개요

  • 이번 PR에서는 다음 5문제의 풀이를 포함합니다.
  • 각 문제에 대한 풀이 과정과 접근 방식을 설명합니다.

✅ 문제 해결 여부

  • 문제 1
  • 문제 2
  • 문제 3
  • 문제 4
  • 문제 5

💡 풀이 방법

문제 1: 양팔저울

문제 난이도
골드 3

문제 유형
DP

접근 방식 및 풀이
추를 올리거나 반대쪽에 올리거나 안올리거나 3가지 방식으로 dfs활용하여 풀이하였습니다.

static void dfs(int cnt, int weight) {
		if (cnt > n || weight < 0 || weight > 15001 || chk[cnt][weight])
			return;

		chk[cnt][weight] = true; // cnt 번째까지의 추를 고려했을 때의 가능한 무게

		if (cnt == n)
			return;

		dfs(cnt + 1, weight + w[cnt]); // 추를 올리거나
		dfs(cnt + 1, weight); // 추를 사용하지 않거나
		dfs(cnt + 1, Math.abs(weight - w[cnt])); // 추를 구슬쪽에 올리거나
	}

문제 2: 제곱수의 합

문제 난이도
실버 2

문제 유형
DP

접근 방식 및 풀이
어떤 수를 구성하는 최소갯수의 제곱수를 구하는 문제였습니다.
arr[n-i*i] 에 1을 더하는 방식으로 dp 배열을 구해 풀었습니다.

dp[0] = 0;
        dp[1] = 1;
        dp[2] = 2;
        dp[3] = 3;

        for (int i = 4; i <= n; i++) {
            dp[i] = i;
            for (int j = 1; j * j <= i; j++) { // 제곱수 이전이 있다면 그 이전꺼 + 제곱수 1개
                dp[i] = Math.min(dp[i], dp[i - j * j] + 1);
            }
        }

문제 3: 로봇 청소기

문제 난이도
골드 5

문제 유형
시뮬레이션

접근 방식 및 풀이
로봇청소기의 작동조건에 따라 시뮬레이션을 구현하여 풀이하였습니다.

static void run() {
		while (true) {
			if (map[c.y][c.x] == 0) {
				map[c.y][c.x] = 2;
				res++;
			}

			boolean chk = false;

			for (int d = 0; d < 4; d++) { // 4방향 중 청소할 곳 있는지 탐색
				int dy = c.y + dir[d][0];
				int dx = c.x + dir[d][1];
				if (dy < 0 || dy >= n || dx < 0 || dx >= m)
					continue;
				if (map[dy][dx] == 0) {
					chk = true;
					break;
				}
			}
			if (chk) { // 청소할 곳이 있다면 왼쪽으로 90도 돌아서 확인
				c.dir = turn[c.dir];
				int dy = c.y + dir[c.dir][0];
				int dx = c.x + dir[c.dir][1];
				if (dy < 0 || dy >= n || dx < 0 || dx >= m)
					continue;
				if (map[dy][dx] == 0) {
					c.y = dy;
					c.x = dx;
				}
			} else { // 청소할 곳이 없다면 뒤로 한칸 이동
				int dy = c.y + dir[round[c.dir]][0];
				int dx = c.x + dir[round[c.dir]][1];
				if (dy < 0 || dy >= n || dx < 0 || dx >= m || map[dy][dx] == 1)
					return;
				else {
					c.y = dy;
					c.x = dx;
				}
			}
		}
	}

문제 4: 연구소 3

문제 난이도
골드 3

문제 유형
그래프

접근 방식 및 풀이
bfs를 활용하며 전염시키는 각 칸에 도착하는 시간을 저장하는 배열을 사용하고
bfs 완료 후에 모든 칸이 전염되었으면 결과값을 갱신하는 식으로 구현했습니다.

static void bfs(boolean[][] visited, Queue<int[]> q) {
	    int[][] time = new int[n][n]; // 각 칸별 감염되는 시간을 저장할 배열
	    int max = 0;

	    while (!q.isEmpty()) {
	        int[] cur = q.poll();
	        for (int d = 0; d < 4; d++) {
	            int dy = cur[0] + dir[d][0];
	            int dx = cur[1] + dir[d][1];

	            if (dy >= 0 && dy < n && dx >= 0 && dx < n && map[dy][dx] != 1 && !visited[dy][dx]) {
	                visited[dy][dx] = true; // 감염 가능한 구역을 찾아서 감염시키고 시간 저장
	                time[dy][dx] = time[cur[0]][cur[1]] + 1;
	                q.add(new int[] { dy, dx });
	            }
	        }
	    }

        // 모든 탐색이 끝나면 전 지역을 감염시켰는지 확인
	    boolean success = true;
	    for (int i = 0; i < n; i++) {
	        for (int j = 0; j < n; j++) {
	            if (map[i][j] == 0) {
	                if (!visited[i][j]) {
	                    success = false;
	                    break;
	                } else {
	                    max = Math.max(max, time[i][j]);
	                }
	            }
	        }
	    }

	    if (success) { // 모두 감염 시켰다면 res 갱신
	        res = Math.min(res, max);
	    }
	}

초기에 활성화 되는 바이러스는 조합을 이용하여 찾고 그 안에서 bfs 탐색하였습니다.

static void combination(int cnt, int start) { // 처음 활성화시키는 바이러스 조합 구하고 탐색
		if (cnt == m) {
			boolean[][] visited = new boolean[n][n];
			Queue<int[]> q = new ArrayDeque<>();
			for (int i = 0; i < m; i++) {
				int[] cur = virus.get(num[i]);
				visited[cur[0]][cur[1]] = true;
				q.add(cur);
			}
			bfs(visited, q);
			return;
		}

		for (int i = start; i < virus.size(); i++) {
			num[cnt] = i;
			combination(cnt + 1, i + 1);
		}
	}

문제 5 : 타일 채우기

문제 난이도
골드 4

문제 유형
DP

접근 방식 및 풀이
타일의 칸을 직접 그려보며 점화식을 찾아서 dp 구현했습니다.

int[] dp = new int[31]; // 최대 30칸 까지
		dp[0] = 1;
		dp[1] = 0;
		dp[2] = 3;

		for (int i = 4; i <= n; i += 2) { // 점화식을 이용한 dp 풀이
			dp[i] = 3 * dp[i - 2];
			for (int j = 4; j <= i; j += 2) {
				dp[i] += 2 * dp[i - j];
			}
		}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant