Skip to content

Commit 38550d4

Browse files
authored
Merge pull request #22 from yeahdy/main
[2주차] 이예진
2 parents 67246b8 + 3fa7fcb commit 38550d4

11 files changed

+503
-24
lines changed

BOJ/1000-10000번/YJ_1647.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import java.io.BufferedReader;
2+
import java.io.IOException;
3+
import java.io.InputStreamReader;
4+
import java.util.Arrays;
5+
import java.util.Comparator;
6+
7+
/**
8+
* 알고리즘: 최소신장트리(MST) > 크루스칼 알고리즘
9+
* 시간복잡도: M은 1이상 1,000,000이하이므로 O(NLogN)
10+
* 아이디어:
11+
* > 최소 신장 트리 조건을 충족하는 문제
12+
* - 같은 마을안에서는 집 사이에 경로가 존재하지만, 길을 없앨 수 있다.
13+
* - 순환 싸이클이 아니더라도 집끼리 연결만 되어 있으면 됨
14+
* - 연결된 경로의 사이는 최소값으로만 연결
15+
* 추가 요구사항
16+
* - 분리된 두 마을 사이에 있는 길들은 없애도 된다
17+
*/
18+
public class YJ_1647 {
19+
public static void main(String[] args) throws IOException {
20+
BufferedReader sc = new BufferedReader(new InputStreamReader(System.in));
21+
String[] first = sc.readLine().split("\\s");
22+
int N = Integer.parseInt(first[0]);
23+
int M = Integer.parseInt(first[1]);
24+
int[][] hometown = new int[M][3];
25+
for(int i=0; i<M; i++){
26+
String[] line = sc.readLine().split("\\s");
27+
int[] set = new int[line.length];
28+
for(int j=0; j<line.length; j++){
29+
set[j] = Integer.parseInt(line[j]);
30+
}
31+
hometown[i]= set;
32+
}
33+
34+
System.out.println(getMinMaintenance(N, hometown));
35+
}
36+
37+
static int getMinMaintenance(int N,int[][] hometown){
38+
int cost = 0;
39+
int[] parent = new int[N+1];
40+
//자기 자신을 부모로 가지도록 초기값 설정
41+
for(int i=1; i<N+1; i++){
42+
parent[i] = i;
43+
}
44+
//유지비 오름차순 정렬 > 유지비가 적은것부터 계산
45+
Arrays.sort(hometown, Comparator.comparingInt(o -> o[2])); //O(NlogN)
46+
47+
int maxCost = 0;
48+
for(int i=0; i<hometown.length; i++){ //O(M)
49+
if(find(parent, hometown[i][0]) != find(parent, hometown[i][1])){
50+
//최소 유지비 누적
51+
cost += hometown[i][2];
52+
maxCost= Math.max(maxCost,hometown[i][2]);
53+
//집합의 부모가 같도록 병합
54+
union(parent,hometown[i][0],hometown[i][1]);
55+
}
56+
}
57+
return cost-maxCost;
58+
}
59+
60+
//집합의 부모 찾기
61+
private static int find(int[] parent, int i){
62+
if(parent[i] == i){
63+
return i;
64+
}
65+
return find(parent, parent[i]);
66+
}
67+
68+
//집합의 더 작은 부모로 병합하기
69+
private static void union(int[] parent, int a, int b){
70+
int parentA = find(parent,a);
71+
int parentB = find(parent,b);
72+
//더 작은 부모의 값을 다른 배열의 부모값으로 변경해서 합치기(배열의 값이 같을 경우 같은 부모)
73+
if(parentA > parentB){
74+
parent[parentA] = parentB;
75+
}else{
76+
parent[parentB] = parentA;
77+
}
78+
}
79+
80+
}

BOJ/1000-10000번/YJ_2631.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import java.util.*;
2+
import java.io.*;
3+
4+
/**
5+
* 알고리즘: DP > 최장증가 부분수열(Longest Increasing Subsequence)
6+
* 시간복잡도: 2 <= N <= 200 이므로 신경쓰지 않아도 됨
7+
* 아이디어:
8+
* - 어떤 기준으로 정렬을 해야 하는지?
9+
* 최소 이동 횟수는 이미 정렬된 수는 제외하고, 나머지 정렬 안된 수들만 움직이기
10+
* - 이미 정렬된 수는 제외하는 기준?
11+
* 주어진 숫자들에서 오름차순으로 가장 길게 정렬된 수는 이동하지 않아도 됨
12+
*- 최장 오름차순 정렬 수 구하는 방법?
13+
* 현재 값과 이전 값을 비교해서 이전 값이 더 작을 경우, 현재 정렬수(기본 1) +1 한다 (누적)
14+
* 반복을 통해 현재 값과 이전 값들을 비교해서 가장 높은 정렬 수로 현재 값을 갱신한다
15+
* 따라서 (전체 숫자 수 - 최장 오름차순 길이)를 한 나머지 개수가 움직여야 하는 갯수가 된다.
16+
*/
17+
public class YJ_2631 {
18+
public static void main(String[] args) throws IOException {
19+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
20+
int children = Integer.parseInt(br.readLine());
21+
int[] line = new int[children];
22+
for(int i=0; i<children; i++){
23+
line[i] = Integer.parseInt(br.readLine());
24+
}
25+
26+
System.out.println(getMinChanged(children,line));
27+
}
28+
29+
static int getMinChanged(int children,int[] line){
30+
int [] dp = new int[children];
31+
for(int i=0; i<children; i++){
32+
dp[i] = 1; //최소값 1
33+
for(int j=0; j<i; j++){
34+
//line의 이전[j] 값들이 현재(i) 값보다 작고,
35+
//dp의 이전 값+1이 현재 값보다 클 경우 최장 정렬 수 갱신
36+
if(line[j] < line[i] && dp[j]+1 > dp[i]){
37+
dp[i] = dp[j]+1;
38+
}
39+
}
40+
}
41+
Arrays.sort(dp); //오름차순 정렬 시 마지막 수가 최장 정렬 수
42+
return children - dp[children-1];
43+
}
44+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import java.util.LinkedList;
2+
import java.util.Queue;
3+
import java.util.Scanner;
4+
5+
/**
6+
* 알고리즘: BFS
7+
* 시간복잡도:3 ≤ n, m ≤ 50 범위로 BFS 의 O(n)로 가능
8+
* 아이디어:
9+
* BFS로 순회할 때 요구사항에 맞는 구현을 잘 정리해서 로직을 작성해야함
10+
* 1.자동차는 첫 시작을 기준으로 좌회전한다
11+
* 2.해당 방향이 방문했거나 인도인 경우 계속 좌회전한다
12+
* 3.좌회전 중 도로가 있을 경우 이동한다
13+
* 4.만약 4방향 모두 전진이 불가할 경우 바라보는 방향을 유지한 채로 한칸 후진한다
14+
* 5.후진한 후 4방향을 탐색한다
15+
* 6.후진이 불가하다면 작동을 멈춘다
16+
*/
17+
public class YJ_자율주행_자동차 {
18+
//자동차 방향: 상-좌-하-우
19+
static int[][] direction = {{-1,0}, {0,-1}, {1,0}, {0,1}};
20+
static int[][] road = null;
21+
static Queue<int[]> queue = new LinkedList<>();
22+
23+
public static void main(String[] args) {
24+
Scanner sc = new Scanner(System.in);
25+
String[] firstLine = sc.nextLine().split("\\s");
26+
String[] secondLine = sc.nextLine().split("\\s");
27+
28+
int N = Integer.parseInt(firstLine[0]); //세로
29+
int M = Integer.parseInt(firstLine[1]); //가로
30+
road = new int[N][M];
31+
for (int i = 0; i < N; i++) { //길 데이터 채우기
32+
String[] line = sc.nextLine().split("\\s");
33+
for (int j = 0; j < M; j++) {
34+
road[i][j] = Integer.parseInt(line[j]);
35+
}
36+
}
37+
38+
//자동차 현재위치
39+
int X = Integer.parseInt(secondLine[0]);
40+
int Y = Integer.parseInt(secondLine[1]);
41+
queue.offer(new int[]{X, Y});
42+
road[X][Y] = -1;
43+
44+
int D = Integer.parseInt(secondLine[2]); //북-동-남-서
45+
int result = 1;
46+
switch (D) {
47+
case 0:
48+
result = bfs(0);
49+
break;
50+
case 1:
51+
result = bfs(3);
52+
break;
53+
case 2:
54+
result = bfs(2);
55+
break;
56+
case 3:
57+
result = bfs(1);
58+
break;
59+
}
60+
61+
System.out.println(result);
62+
}
63+
64+
65+
private static int bfs(int startD) {
66+
int visited = 1;
67+
while (!queue.isEmpty()) {
68+
int[] current = queue.poll();
69+
int x = current[0];
70+
int y = current[1];
71+
int directionIndex = startD;
72+
73+
for (int i = 0; i < 4; i++) {
74+
int nx = x + direction[directionIndex][0];
75+
int ny = y + direction[directionIndex][1];
76+
77+
if (nx >= 0 && nx < road.length && ny >= 0 && ny < road[0].length && road[nx][ny] == 0) {
78+
queue.offer(new int[]{nx, ny});
79+
road[nx][ny] = -1;
80+
visited++;
81+
break;
82+
}
83+
84+
directionIndex = (directionIndex + 1) % 4;
85+
}
86+
87+
// 후진
88+
if(queue.isEmpty()){
89+
int backX = x - direction[startD][0];
90+
int backY = y - direction[startD][1];
91+
if (backX >= 0 && backX < road.length && backY >= 0 && backY < road[0].length && road[backX][backY] == 0) {
92+
queue.offer(new int[]{backX, backY});
93+
road[backX][backY] = -1;
94+
visited++;
95+
} else {
96+
break;
97+
}
98+
}
99+
}
100+
return visited;
101+
}
102+
}

Programmers/Level2/YJ_더_맵게.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import java.util.PriorityQueue;
2+
3+
/**
4+
* 알고리즘: 우선순위 큐
5+
* 시간복잡도: 2 <= scoville <= 1,000,000 크기로 O(NlogN)
6+
* 아이디어:
7+
* 두 수를 합친 후 스코빌 배열에서 오름차순 정렬이 되어야 하기 때문에
8+
* 우선순위 큐를 사용해서 두수를 빼내고, 합친 수를 다시 넣도록 함
9+
* 우선순위 큐는 기본적으로 원소를 오름차순 정렬하기 때문에 큐의 첫번째 원소가 K 보다 크거나 같다면 스코빌 모든 음식의 스코빌 지수가 K 이상 임
10+
*/
11+
public class YJ_더_맵게 {
12+
public int solution(int[] scoville, int K) {
13+
int answer = 0;
14+
PriorityQueue<Integer> queue = new PriorityQueue<>();
15+
for(int s : scoville){
16+
queue.offer(s);
17+
}
18+
19+
while(queue.size() > 1){
20+
int first = queue.poll();
21+
if(first >= K){
22+
break;
23+
}
24+
int second = queue.poll();
25+
int mixed = calculateScoville(first,second);
26+
queue.offer(mixed);
27+
answer++;
28+
}
29+
30+
if(queue.poll() < K){
31+
return -1;
32+
} else {
33+
return answer;
34+
}
35+
}
36+
37+
//첫번째로 낮은 스코빌 지수 + (두번째로 낮은 스코빌 지수 * 2)
38+
private int calculateScoville(int first, int second){
39+
return first + (second*2);
40+
}
41+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/***
2+
* 알고리즘: 일반구현
3+
* 시간복잡도: N <= 100,000 크기로 O(NlogN)까지 가능
4+
* 아이디어:
5+
* 요구사항은 이전의 행과 같은 열을 밝지 않고, 각 행의 열의 합이 최고점 찾기
6+
* 이전의 행과 현재의 행을 비교하는데, 이전 행의 열들 중 현재 행과 같은 열을 제외하고 최고점을 찾는다
7+
*/
8+
public class YJ_땅따먹기 {
9+
public static void main(String[] args) {
10+
int[][] land ={{1,2,3,5},{5,6,7,8},{4,3,2,1}};
11+
int answer = 0;
12+
13+
// 이전 행의 열들 중 현재 행과 같은 열을 제외하고 최고점 (현재 행의 열: 0 , 이전행의 열: 1,2,3)
14+
// 각 행마다 이전 행의 최고점 열을 누적해서 더하기
15+
for(int i=1; i<land.length; i++){
16+
land[i][0] += maxLand(land[i-1][1],land[i-1][2],land[i-1][3]);
17+
land[i][1] += maxLand(land[i-1][0],land[i-1][2],land[i-1][3]);
18+
land[i][2] += maxLand(land[i-1][0],land[i-1][1],land[i-1][3]);
19+
land[i][3] += maxLand(land[i-1][0],land[i-1][1],land[i-1][2]);
20+
}
21+
22+
// 마지막 행에 모든 행들의 누적 최고점 열이 있음
23+
int maxScore = 0;
24+
for(int i=0; i<land[0].length; i++){
25+
maxScore = Math.max(maxScore,land[land.length-1][i]);
26+
}
27+
System.out.println(answer);
28+
}
29+
30+
private static int maxLand(int first, int second, int third){
31+
return Math.max(Math.max(first,second),third);
32+
}
33+
}

Programmers/Level2/YJ_방문길이.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import java.util.HashSet;
12
import java.util.LinkedList;
23
import java.util.Queue;
34

@@ -6,19 +7,21 @@
67
* 시간복잡도: O(n)
78
* 아이디어:
89
* BFS로 순회할때 방문한 지점을 방문처리 하는 것이 아닌 다녀간 길을 방문처리 해야 함
9-
* 다녀간 길을 표시하는 방법?
10-
*
10+
- 현재 위치(x,y) + 다음 위치(x,y) 를 문자열 형태로 저장
11+
> 중복일 경우 이미 다녀간 경로!
12+
- 다음 위치(x,y) + 현재 위치(x,y) 를 문자열 형태로 저장
13+
> 위아래 또는 좌우 왔다갔다한 경로도 이미 다녀간 경로!
1114
*/
1215
public class YJ_방문길이 {
1316
public static void main(String[] args) {
14-
String dirs = "ULURRDLLU"; //7
15-
// String dirs = "LULLLLLLU"; //7
17+
// String dirs = "ULURRDLLU"; //7
18+
String dirs = "LULLLLLLU"; //7
1619
System.out.println(solution(dirs));
1720
}
1821

1922
static int answer = 0;
2023
static int[][] direction = {{0,1},{0,-1},{-1,0},{1,0}}; //상,하,좌,우
21-
static boolean[][] visited = new boolean[11][11];
24+
static HashSet<String> visited = new HashSet<>();
2225
static Queue<int[]> queue = new LinkedList<>();
2326
static int solution(String dirs) {
2427
String[] input = dirs.split("");
@@ -27,43 +30,46 @@ static int solution(String dirs) {
2730

2831
//현재위치 방문처리
2932
queue.offer(start);
30-
visited[start[0]][start[1]] = true;
31-
3233
for(String i : input){
3334
switch(i){
3435
case "U":
35-
bfs(visited,direction[0]);
36+
bfs(end,visited,direction[0]);
3637
break;
3738
case "D":
38-
bfs(visited,direction[1]);
39+
bfs(end,visited,direction[1]);
3940
break;
4041
case "L":
41-
bfs(visited,direction[2]);
42+
bfs(end,visited,direction[2]);
4243
break;
4344
case "R":
44-
bfs(visited,direction[3]);
45+
bfs(end,visited,direction[3]);
4546
break;
4647
}
4748
}
4849
return answer;
4950
}
5051

51-
private static void bfs(boolean[][] visited, int[] direction){
52+
private static void bfs(int[] end, HashSet<String> visited, int[] direction){
5253
int[] current = queue.peek();
54+
int x = current[0];
55+
int y = current[1];
5356
//위치 이동
54-
int nx = current[0] + direction[0];
55-
int ny = current[1] + direction[1];
57+
int nx = x + direction[0];
58+
int ny = y + direction[1];
59+
String visitLength = ""+x+y+nx+ny;
60+
String reverseLength = ""+nx+ny+x+y;
5661

57-
if(nx < 0 || nx > visited[0].length -1 || ny < 0 || ny > visited.length-1){
58-
return;
59-
}
60-
if(visited[nx][ny]){
62+
if(nx < 0 || nx > end[0]-1 || ny < 0 || ny > end[1]-1){
6163
return;
6264
}
6365
//방문처리
6466
queue.poll();
65-
visited[nx][ny] = true;
66-
//이동값 갱신
67+
68+
if(visited.contains(visitLength) || visited.contains(reverseLength)){
69+
queue.offer(new int[]{nx,ny});
70+
return;
71+
}
72+
visited.add(visitLength);
6773
queue.offer(new int[]{nx,ny});
6874
answer++;
6975
}

0 commit comments

Comments
 (0)