-
Notifications
You must be signed in to change notification settings - Fork 4
[25주차] 이지영 #339
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
[25주차] 이지영 #339
Changes from all commits
e2d2a63
58dcdde
f861e46
6467140
a449efe
cb23ba0
b069acb
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,71 @@ | ||
import java.io.*; | ||
import java.util.*; | ||
public class JY_12784 { | ||
|
||
static int N, M; | ||
static List<Node>[] g; | ||
static boolean[] visited; | ||
static class Node { | ||
int num, cost; | ||
public Node(int num, int cost) { | ||
this.num = num; | ||
this.cost = cost; | ||
} | ||
@Override | ||
public String toString() { | ||
return "Node [num=" + num + ", cost=" + cost + "]"; | ||
} | ||
|
||
|
||
} | ||
|
||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
|
||
int T = Integer.parseInt(st.nextToken()); | ||
StringBuilder sb = new StringBuilder(); | ||
for(int t=0; t<T; t++) { | ||
st = new StringTokenizer(br.readLine()); | ||
N = Integer.parseInt(st.nextToken()); | ||
M = Integer.parseInt(st.nextToken()); | ||
|
||
g = new ArrayList[N+1]; | ||
for(int i=1; i<N+1; i++) { | ||
g[i] = new ArrayList<>(); | ||
} | ||
|
||
for(int i=0; i<M; i++) { | ||
st = new StringTokenizer(br.readLine()); | ||
int a = Integer.parseInt(st.nextToken()); | ||
int b = Integer.parseInt(st.nextToken()); | ||
int c = Integer.parseInt(st.nextToken()); | ||
g[a].add(new Node(b, c)); | ||
g[b].add(new Node(a, c)); | ||
} | ||
|
||
visited = new boolean[N+1]; | ||
visited[1] = true; | ||
int ans = dfs(1); | ||
sb.append(ans+"\n"); | ||
} | ||
|
||
System.out.println(sb.toString()); | ||
} | ||
public static int dfs(int now) { | ||
visited[now] = true; | ||
|
||
// 리프노드라면 자신의 비용 반환 | ||
if(now !=1 && g[now].size() == 1) return g[now].get(0).cost; | ||
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밖에 없을 때랑 리프노드 판단하는거 이렇게 하면 되는거였군요... |
||
|
||
// 리프노드 아님 => 자식 순회 | ||
int minCost = 0; | ||
for(Node next: g[now]) { | ||
if(visited[next.num]) continue; | ||
minCost += Math.min(next.cost, dfs(next.num)); | ||
} | ||
|
||
return minCost; | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import java.io.*; | ||
import java.util.*; | ||
|
||
public class JY_32070 { | ||
static int N; | ||
// cnt[i] 그룹의 공의 개수 == 그룹의 크기 | ||
// rank[i] 트리의 깊이 | ||
// toParis[] 한 그룹에서 상단에 위치한 공의 개수 | ||
static int[] parent, cnt, topPairs; | ||
static boolean[] solved; | ||
static List<Integer>[] ball; | ||
|
||
static int find(int u) { | ||
if (parent[u] == u) return u; | ||
return parent[u] = find(parent[u]); | ||
} | ||
|
||
static void union(int a, int b) { | ||
int pa = find(a); | ||
int pb = find(b); | ||
|
||
if(pa == pb) return; | ||
if(pa < pb) { | ||
parent[pb] = pa; | ||
cnt[pa] += cnt[pb]; | ||
} else { | ||
parent[pa] = pb; | ||
cnt[pb] += cnt[pa]; | ||
} | ||
|
||
} | ||
|
||
// 해당 집합의 크기 반환 | ||
static int getCnt(int u) { | ||
return cnt[find(u)]; | ||
} | ||
|
||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
N = Integer.parseInt(br.readLine()); | ||
|
||
ball = new ArrayList[N + 1]; | ||
for (int i = 1; i <= N; i++) { | ||
ball[i] = new ArrayList<>(); | ||
} | ||
|
||
parent = new int[N + 1]; | ||
// rank = new int[N + 1]; | ||
cnt = new int[N + 1]; | ||
topPairs = new int[N + 1]; | ||
solved = new boolean[N + 1]; | ||
|
||
// 초기화 == 각 상자가 그룹장 | ||
for (int i = 1; i <= N; i++) { | ||
parent[i] = i; | ||
cnt[i] = 1; | ||
} | ||
|
||
for (int i = 1; i <= N; i++) { | ||
StringTokenizer st = new StringTokenizer(br.readLine()); | ||
int a = Integer.parseInt(st.nextToken()); | ||
int b = Integer.parseInt(st.nextToken()); | ||
|
||
// 색깔이 a인 공의 절대적인 상자 위치 | ||
ball[a].add(i * 2); | ||
// 색깔이 b인 공의 절대적인 상자 위치 | ||
ball[b].add(i * 2 + 1); | ||
} | ||
|
||
System.out.println(Arrays.toString(ball)); | ||
|
||
// 같은 색 공이 있는 상자들을 병합 | ||
for (int i = 1; i <= N; i++) { | ||
union(ball[i].get(0) / 2, ball[i].get(1) / 2); | ||
} | ||
|
||
System.out.println(">> parent: "+Arrays.toString(parent)); | ||
System.out.println(">> cnt: "+Arrays.toString(cnt)); | ||
// cnt[i] : i번째 상자가 속한 사이클의 상자의 개수 | ||
|
||
// 루트 노드의 topPairs 개수 증가 | ||
// 짝수 : 상자의 상단에 있음 | ||
// 홀수 : 상자의 하단에 있음 | ||
for (int i = 1; i <= N; i++) { | ||
// 색깔이 i인 공이 모두 각 상자의 상단에 있음 | ||
if (ball[i].get(0) % 2 == 0 && ball[i].get(1) % 2 == 0) { | ||
int rootIdx = find(ball[i].get(0) / 2); | ||
System.out.println("i:"+i+" root:"+rootIdx); | ||
topPairs[rootIdx]++; | ||
} | ||
} | ||
|
||
System.out.println("top: "+Arrays.toString(topPairs)); | ||
|
||
// 상자 그룹이 2개 이상이면 불가능 (-1 출력) | ||
for (int i = 1; i <= N; i++) { | ||
int rootIdx = find(ball[i].get(0) / 2); | ||
if (topPairs[rootIdx] >= 2) { | ||
System.out.println("-1"); | ||
return; | ||
} | ||
} | ||
|
||
int ans = 0; | ||
|
||
// 최소 이동 횟수 계산 | ||
for (int i = 1; i <= N; i++) { | ||
int rootIdx = find(ball[i].get(0) / 2); | ||
|
||
if (solved[rootIdx]) continue; | ||
|
||
solved[rootIdx] = true; | ||
int x = cnt[rootIdx]; | ||
|
||
if (x >= 2) ans += x + 1; | ||
} | ||
|
||
System.out.println(ans); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import java.util.*; | ||
import java.io.*; | ||
public class JY_9944 { | ||
|
||
static final int INF = 1000001; | ||
static int N, M; | ||
static char[][] g; | ||
// 상 하 좌 우 | ||
static int[] dx = {-1, 1, 0, 0}; | ||
static int[] dy = {0, 0, -1, 1}; | ||
static boolean[][] visited; | ||
static int eCnt = 0; | ||
static int ans; | ||
|
||
public static void main(String[] args) throws IOException { | ||
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
StringTokenizer st; | ||
String line; | ||
|
||
int t = 1; | ||
while((line = br.readLine()) != null && !line.isEmpty()) { | ||
st = new StringTokenizer(line); | ||
|
||
N = Integer.parseInt(st.nextToken()); | ||
M = Integer.parseInt(st.nextToken()); | ||
|
||
g = new char[N][M]; | ||
eCnt = 0; | ||
for(int i=0; i<N; i++) { | ||
String str = br.readLine(); | ||
for(int j=0; j<M; j++) { | ||
g[i][j] = str.charAt(j); | ||
if(g[i][j] == '.') eCnt++; | ||
} | ||
} | ||
|
||
ans = INF; | ||
|
||
// 시작점 | ||
for(int i=0; i<N; i++) { | ||
for(int j=0; j<M; j++) { | ||
if(g[i][j] == '*') continue; | ||
visited = new boolean[N][M]; | ||
for(int d=0; d<4; d++) { | ||
int nx = i + dx[d]; | ||
int ny = j + dy[d]; | ||
// d방향으로 이동 가능하면 단계 1부터 시작 | ||
if(canGo(nx, ny)) { | ||
dfs(i, j, d, 1, 1); | ||
} | ||
// 불가능하면 단계 2부터 시작 | ||
else { | ||
dfs(i, j, d, 1, 0); | ||
} | ||
Comment on lines
+52
to
+54
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. d 방향으로 이동이 불가능하면 이 과정이 없어도 될 것 같다고 생각하는데, 왜 있는지 궁금합니다! 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.
d방향으로 움직일 수 없는 경우 0으로 시작하면 이후 탐색에서 움직을 수 있는 방향을 찾아 단계1로 시작되도록 했습니다. 이는 위 테스트케이스 처럼 움직일 수 있는 곳이 딱 1칸일 경우는 시작하자마자 종료되기 때문에 최소 이동횟수가 0이되야하는데 아예 탐색을 안하면 -1이되기 때문에 탐색을 진행해서 최소 움직임 횟수를 0으로 출력하도록 하기 위해 작성했습니다.
|
||
|
||
} | ||
} | ||
} | ||
System.out.print("Case "+t+": "); | ||
if(ans == INF) System.out.println(-1); | ||
else System.out.println(ans); | ||
t++; | ||
} | ||
|
||
|
||
} | ||
public static void printG() { | ||
for(int i=0; i<N; i++) { | ||
System.out.println(Arrays.toString(g[i])); | ||
} | ||
System.out.println(); | ||
} | ||
public static boolean inRange(int x, int y) { | ||
return x>=0 && x<N && y>=0 && y<M; | ||
} | ||
public static boolean canGo(int x, int y) { | ||
return inRange(x, y) && !visited[x][y] && g[x][y] != '*'; | ||
} | ||
public static void dfs(int x, int y, int dir, int mCnt, int cnt) { | ||
// 모든 칸 탐색함 | ||
if(mCnt == eCnt) { | ||
ans = Math.min(ans, cnt); | ||
return; | ||
} | ||
// 현재 이동 경로의 수가 저장된 정답보다 크다면 진행X | ||
if(cnt >= ans || cnt >= INF) return; | ||
|
||
visited[x][y] = true; | ||
int nx = x + dx[dir]; | ||
int ny = y + dy[dir]; | ||
|
||
// 현재 방향으로 갈 수 있음 | ||
if(canGo(nx, ny)) { | ||
dfs(nx, ny, dir, mCnt+1, cnt); | ||
} | ||
// 갈 수 없음 -> 방햔 전환 필요(단계 증가) | ||
else { | ||
boolean isMove = false; | ||
for(int i=0; i<4; i++) { | ||
if(i == dir) continue; | ||
nx = x + dx[i]; | ||
ny = y + dy[i]; | ||
if(!canGo(nx, ny)) continue; | ||
|
||
isMove = true; | ||
dfs(nx, ny, i, mCnt+1, cnt+1); | ||
} | ||
|
||
} | ||
visited[x][y] = false; | ||
} | ||
|
||
} |