-
Notifications
You must be signed in to change notification settings - Fork 4
[9주차] 백제완 #124
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
[9주차] 백제완 #124
Changes from all commits
bfa5ea6
56483f8
67a5d1c
f736211
68343c9
bd199bd
80e6fd2
6d7f679
21dff27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import java.util.Arrays; | ||
|
||
public class JW_2098 { | ||
static int n; | ||
static int[][] distance; // 각 거리를 정보 | ||
static int[][] dp; // 메모이제이션을 위한 DP배열 | ||
static int INF = Integer.MAX_VALUE >> 2; // 적절한 최댓값 | ||
|
||
public static void main(String[] args) throws Exception { | ||
n = read(); | ||
distance = new int[n][n]; | ||
for (int i = 0; i < n; i++) | ||
for (int j = 0; j < n; j++) { | ||
int d = read(); | ||
// 거리 정보가 없는 경우에는 최댓값으로 설정 | ||
if (d == 0) | ||
d = INF; | ||
distance[i][j] = d; | ||
} | ||
dp = new int[n][1 << n]; | ||
// dp배열 초기화 | ||
for (int i = 0; i < n; i++) | ||
Arrays.fill(dp[i], -1); | ||
// 0번 도시에서 출발하는 외판원 순회 | ||
int result = tsp(0, 1); | ||
System.out.println(result); | ||
} | ||
|
||
// 외판원 순회 | ||
// @param city 현재 도시 | ||
// @param visited 비트마스킹 방문처리 | ||
private static int tsp(int city, int visited) { | ||
// 모든 도시를 방문했다면 | ||
if (visited == (1 << n) - 1) | ||
// 원래 도시로 돌아가는 거리를 반환 | ||
return distance[city][0]; | ||
// 미리 계산된 최솟값이 있다면 반환 | ||
if (dp[city][visited] != -1) | ||
return dp[city][visited]; | ||
int result = INF; // 해당 도시를 방문했을 때 최솟값을 구하기 위한 변수 | ||
for (int nextCity = 0; nextCity < n; nextCity++) { | ||
// 방문한 도시라면 건너뜀 | ||
if ((visited & (1 << nextCity)) != 0) | ||
continue; | ||
// 다음 도시를 방문 | ||
int temp = distance[city][nextCity] + tsp(nextCity, visited | (1 << nextCity)); | ||
// 해당 도시에서 가질 수 있는 최솟값 갱신 | ||
result = Math.min(result, temp); | ||
} | ||
// 계산된 값으로 메모이제이션 | ||
dp[city][visited] = result; | ||
return result; | ||
} | ||
|
||
// 빠른 입력 함수 | ||
private static int read() throws Exception { | ||
int c, n = System.in.read() & 15; | ||
while ((c = System.in.read()) >= 48) | ||
n = (n << 3) + (n << 1) + (c & 15); | ||
if (c == 13) | ||
System.in.read(); | ||
return n; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import java.io.BufferedReader; | ||
import java.io.InputStreamReader; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.StringTokenizer; | ||
|
||
public class JW_2660 { | ||
|
||
static final int INF = Integer.MAX_VALUE >> 2; | ||
|
||
public static void main(String[] args) throws Exception { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
int n = Integer.parseInt(br.readLine()); | ||
// 그래프 선언 및 초기화 | ||
int[][] graph = new int[n + 1][n + 1]; | ||
for (int i = 0; i < n + 1; i++) { | ||
Arrays.fill(graph[i], INF); | ||
graph[i][i] = 0; | ||
} | ||
while (true) { | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
int u = Integer.parseInt(st.nextToken()); | ||
int v = Integer.parseInt(st.nextToken()); | ||
// 종료 조건 | ||
if (u == -1 && v == -1) | ||
break; | ||
// 양방향 그래프 | ||
graph[u][v] = 1; | ||
graph[v][u] = 1; | ||
} | ||
// 플로이드 와샬 | ||
for (int k = 1; k < n + 1; k++) | ||
for (int i = 1; i < n + 1; i++) | ||
for (int j = 1; j < n + 1; j++) | ||
if (graph[i][j] > graph[i][k] + graph[k][j]) { | ||
graph[i][j] = graph[i][k] + graph[k][j]; | ||
} | ||
int min = 50; // 최소 스코어 | ||
ArrayList<Integer> al = new ArrayList<>(); | ||
for (int i = 1; i < n + 1; i++) { | ||
int score = 0; | ||
// 최단 거리 중 최댓값 찾기 | ||
for (int j = 1; j < n + 1; j++) | ||
score = Math.max(score, graph[i][j]); | ||
// 최솟값을 갱신 할 수 있다면 | ||
if (min > score) { | ||
min = score; // 최솟값 갱신 | ||
al.clear(); // 리스트 비우기 | ||
al.add(i); // 리스트에 추가 | ||
// 최솟값과 동일하면 | ||
} else if (min == score) | ||
al.add(i); // 리스트에 추가 | ||
} | ||
StringBuilder sb = new StringBuilder(); | ||
sb.append(max).append(" ").append(al.size()).append("\n"); | ||
for (int i : al) { | ||
sb.append(i).append(" "); | ||
} | ||
System.out.println(sb); | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 제완님! 플로이드로 푸셨길래 문제에서 이해 안되는 부분 질문 드립니다 "예를 들어 어느 회원이 다른 모든 회원과 친구이면, 이 회원의 점수는 1점이다. 어느 회원의 점수가 2점이면, 다른 모든 회원이 친구이거나 친구의 친구임을 말한다. 또한 어느 회원의 점수가 3점이면, 다른 모든 회원이 친구이거나, 친구의 친구이거나, 친구의 친구의 친구임을 말한다." 점수 1점 : 회원A-회원B 친구 "각 회원의 점수를 정할 때 주의할 점은 어떤 두 회원이 친구사이이면서 동시에 친구의 친구사이이면, 이 두사람은 친구사이라고 본다. " -> 최단 거리를 고려(??) 모든 사람 최소 점수 구하기 -> 플로이드??? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 혜원님! 점수를 누적하는게 아니라 한 회원의 모든 친구 정보를 파악해서 최종 점수를 매기는 것 입니다!
이런식으로 점수를 계산하기 때문에 한 회원이 다른 회원으로 가는 최단거리를 구해서 그 값중 가장 먼 값이 점수가 됩니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 일단 문제에서 플로이드 와샬을 적용하는 이유를 알려드릴게요!
일단 1번 조건으로 인해서 예를 들어 1 → 2의 점수를 정할 때, 1과 2가 직접 연결되지 않았으면 다른 사람을 통해서 점수를 계산해야 합니다.
해당 조건에 의해서 한 회원의 최단 거리 정보들 중에서 최댓값이 해당 회원의 최종 점수가 됩니다.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 두 분 모두 방향 잡아주셔서 정말 감사합니다 ㅠㅠ 제가 예시를 잘못 이해하고 있었네요
예시를 잘못 이해해서.. 어떤 경우에 2점인지 3점인지.. 이해를 못하고 있었습니다
질문 드리고 또 잘못된 방향으로 이해하고 있었습니다..
제가 올바르게 이해한게 맞을까요.....? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import java.util.Arrays; | ||
|
||
public class JW_13164 { | ||
|
||
public static void main(String[] args) throws Exception { | ||
int n = read(), k = read(); | ||
int[] arr = new int[n]; | ||
for (int i = 0; i < n; i++) | ||
arr[i] = read(); | ||
// 다음 사람과 같은 조가 되었을 때 비용을 저장할 배열 | ||
int[] diff = new int[n - 1]; | ||
// 다음 사람과의 키 차이 계산 | ||
for (int i = 0; i < n - 1; i++) | ||
diff[i] = arr[i + 1] - arr[i]; | ||
// 오름차 순으로 정렬 | ||
Arrays.sort(diff); | ||
int answer = 0; | ||
// 키 차이가 별로 안나는 조합은 묶어도 됨 | ||
for (int i = 0; i < n - k; i++) | ||
answer += diff[i]; | ||
System.out.println(answer); | ||
} | ||
|
||
private static int read() throws Exception { | ||
int c, n = System.in.read() & 15; | ||
while ((c = System.in.read()) >= 48) | ||
n = (n << 3) + (n << 1) + (c & 15); | ||
if (c == 13) | ||
System.in.read(); | ||
return n; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
public class JW_24620 { | ||
static int n; | ||
static int[][] board; | ||
static boolean[][] visited; | ||
// 현재 위치 + 상하좌우를 확인하기 위한 변화량 | ||
static int[] dy = { 0, 1, -1, 0, 0 }; | ||
static int[] dx = { 0, 0, 0, 1, -1 }; | ||
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 방향벡터에 (0, 0)도 추가해주신 점 좋은 것 같습니다 👍 |
||
static int min = Integer.MAX_VALUE; | ||
|
||
public static void main(String[] args) throws Exception { | ||
n = read(); | ||
board = new int[n][n]; | ||
visited = new boolean[n][n]; | ||
for (int i = 0; i < n; i++) | ||
for (int j = 0; j < n; j++) | ||
board[i][j] = read(); | ||
// 완전 탐색 | ||
recursive(0, 0, 0); | ||
System.out.println(min); | ||
} | ||
|
||
private static void recursive(int depth, int total, int p) { | ||
// 3개를 다 심었다면 최솟값 갱신 | ||
if (depth == 3) { | ||
min = Math.min(min, total); | ||
return; | ||
} | ||
// 심을 수 있는 위치 찾기 | ||
for (int i = p; i < n * n; i++) { | ||
int y = i / n, x = i % n; | ||
boolean isPossible = true; | ||
// 모든 유효성을 통과하는지 확인 | ||
for (int j = 0; j < 5; j++) { | ||
int ny = y + dy[j]; | ||
int nx = x + dx[j]; | ||
if (!isValid(ny, nx)) { | ||
isPossible = false; | ||
} | ||
} | ||
// 심을 수 있는 위치일 경우 | ||
if (isPossible) { | ||
int sum = 0; | ||
// 방문 처리 | ||
for (int j = 0; j < 5; j++) { | ||
int ny = y + dy[j]; | ||
int nx = x + dx[j]; | ||
visited[ny][nx] = true; | ||
sum += board[ny][nx]; | ||
} | ||
// 다음 깊이의 재귀 진행 | ||
recursive(depth + 1, total + sum, i + 1); | ||
|
||
// 백 트래킹 | ||
for (int j = 0; j < 5; j++) { | ||
int ny = y + dy[j]; | ||
int nx = x + dx[j]; | ||
visited[ny][nx] = false; | ||
} | ||
} | ||
} | ||
} | ||
|
||
// 경계 체크 및 방문하지 않았는지 유효성 검증 | ||
private static boolean isValid(int y, int x) { | ||
return 0 <= y && y < n && 0 <= x && x < n && !visited[y][x]; | ||
} | ||
|
||
// 빠른 입력 함수 | ||
private static int read() throws Exception { | ||
int c, n = System.in.read() & 15; | ||
while ((c = System.in.read()) >= 48) | ||
n = (n << 3) + (n << 1) + (c & 15); | ||
if (c == 13) | ||
System.in.read(); | ||
return n; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import java.io.BufferedReader; | ||
import java.io.InputStreamReader; | ||
import java.util.ArrayDeque; | ||
import java.util.Deque; | ||
import java.util.PriorityQueue; | ||
import java.util.StringTokenizer; | ||
|
||
public class JW_전투_로봇 { | ||
|
||
static int n; | ||
static int[][] board; | ||
static int[] dy = { -1, 1, 0, 0 }; | ||
static int[] dx = { 0, 0, -1, 1 }; | ||
static int level = 2, count = 0, totalMove = 0; | ||
|
||
public static void main(String[] args) throws Exception { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
n = Integer.parseInt(br.readLine()); | ||
board = new int[n][n]; | ||
int sy = 0, sx = 0; | ||
for (int i = 0; i < n; i++) { | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
for (int j = 0; j < n; j++) { | ||
int p = Integer.parseInt(st.nextToken()); | ||
// 초기 로봇 위치 저장 | ||
if (p == 9) { | ||
sy = i; | ||
sx = j; | ||
} else if (p != 0) { | ||
board[i][j] = p; | ||
} | ||
} | ||
} | ||
Deque<int[]> dq = new ArrayDeque<>(); | ||
boolean[][] visited = new boolean[n][n]; | ||
dq.offer(new int[] { 0, sy, sx }); | ||
// BFS | ||
while (!dq.isEmpty()) { | ||
// 처리할 수 있는 몬스터들의 위치에 따라 우선 순위 부여 | ||
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[0] != o2[0] ? o1[0] - o2[0] : o1[1] - o2[1]); | ||
// 깊이 별로 BFS 진행 | ||
int t = dq.size(); | ||
while (t-- > 0) { | ||
int[] cur = dq.poll(); | ||
int y = cur[1], x = cur[2]; | ||
if (visited[y][x]) | ||
continue; | ||
visited[y][x] = true; | ||
// 해당 레벨에서 잡을 수 있는 몬스터가 존재한다면 우선 순위 큐에 저장 | ||
if (isCatch(y, x)) { | ||
pq.offer(cur); | ||
continue; | ||
} | ||
for (int i = 0; i < 4; i++) { | ||
int ny = y + dy[i], nx = x + dx[i]; | ||
if (isValid(ny, nx) && !visited[ny][nx]) { | ||
dq.offer(new int[] { cur[0] + 1, ny, nx }); | ||
} | ||
} | ||
} | ||
// 해당 깊이에서 처리할 수 있는 몬스터를 1개 이상 발견했다면 | ||
if (!pq.isEmpty()) { | ||
// 우선 순위가 가장 높은 몬스터를 처리 | ||
int[] cur = pq.poll(); | ||
totalMove += cur[0]; | ||
int y = cur[1], x = cur[2]; | ||
board[y][x] = 0; | ||
// 없앤 몬스터의 수 갱신과 레벨 업 | ||
count++; | ||
if (count == level) { | ||
level++; | ||
count = 0; | ||
} | ||
// 큐를 비우고 해당 위치에서 다시 시작 | ||
dq.clear(); | ||
dq.offer(new int[] { 0, y, x }); | ||
visited = new boolean[n][n]; | ||
} | ||
} | ||
System.out.println(totalMove); | ||
} | ||
|
||
// 몬스터를 없앨 수 있는지 확인하는 함수 | ||
private static boolean isCatch(int y, int x) { | ||
return 0 < board[y][x] && board[y][x] < level; | ||
} | ||
|
||
// 경계 체크 함수 | ||
private static boolean isValid(int y, int x) { | ||
return 0 <= y && y < n && 0 <= x && x < n && board[y][x] <= level; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import java.util.Arrays; | ||
|
||
class JW_118668 { | ||
public int solution(int alp, int cop, int[][] problems) { | ||
// 모든 문제를 풀기 위한 최솟값을 찾기 위해 초기화 | ||
int maxAlp = alp, maxCop = cop; | ||
for (int i = 0; i < problems.length; i++) { | ||
maxAlp = Math.max(maxAlp, problems[i][0]); | ||
maxCop = Math.max(maxCop, problems[i][1]); | ||
} | ||
// DP 배열 초기화 | ||
int[][] dp = new int[maxAlp + 1][maxCop + 1]; | ||
for (int i = 0; i < maxAlp + 1; i++) | ||
Arrays.fill(dp[i], Integer.MAX_VALUE >> 2); | ||
dp[alp][cop] = 0; | ||
|
||
// DP | ||
// 현재 값 기준으로 다음 값 결정하기 | ||
for (int i = alp; i < maxAlp + 1; i++) { | ||
for (int j = cop; j < maxCop + 1; j++) { | ||
// 알고력 증가 | ||
if (i < maxAlp) | ||
dp[i + 1][j] = Math.min(dp[i + 1][j], dp[i][j] + 1); | ||
// 코딩력 증가 | ||
if (j < maxCop) | ||
dp[i][j + 1] = Math.min(dp[i][j + 1], dp[i][j] + 1); | ||
// 문제 풀기 | ||
for (int[] problem : problems) | ||
// 풀 수 있는 문제라면 | ||
if (i >= problem[0] && j >= problem[1]) { | ||
// 능력치 증가 | ||
int nextAlp = Math.min(maxAlp, i + problem[2]); | ||
int nextCop = Math.min(maxCop, j + problem[3]); | ||
dp[nextAlp][nextCop] = Math.min(dp[nextAlp][nextCop], dp[i][j] + problem[4]); | ||
} | ||
Comment on lines
+30
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 문제를 풀었을 때 코딩력, 알고력 중 어떤걸 올릴지, 둘다 올릴지에 대한 각 경우를 생각해서 if 조건문으로 나눴는데, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞아요! 최대로 넘어가지 않는 범위로 조정해주는 게 편해요! |
||
} | ||
} | ||
return dp[maxAlp][maxCop]; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
각 노드의 거리를 1이라고 설정하면 거리와 깊이의 개념이 같아지기 때문에 플로이드 와셜로 풀이할 수 있네여!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
후후 맞습니다! 담엔 플로이드 와샬로만 풀리는 문제를 내야겠어요...