문제

월드초등학교 학생회장 후보는 일정 기간 동안 전체 학생의 추천에 의하여 정해진 수만큼 선정된다. 그래서 학교 홈페이지에 추천받은 학생의 사진을 게시할 수 있는 사진틀을 후보의 수만큼 만들었다. 추천받은 학생의 사진을 사진틀에 게시하고 추천받은 횟수를 표시하는 규칙은 다음과 같다.

  1. 학생들이 추천을 시작하기 전에 모든 사진틀은 비어있다.
  2. 어떤 학생이 특정 학생을 추천하면, 추천받은 학생의 사진이 반드시 사진틀에 게시되어야 한다.
  3. 비어있는 사진틀이 없는 경우에는 현재까지 추천 받은 횟수가 가장 적은 학생의 사진을 삭제하고, 그 자리에 새롭게 추천받은 학생의 사진을 게시한다. 이때, 현재까지 추천 받은 횟수가 가장 적은 학생이 두 명 이상일 경우에는 그러한 학생들 중 게시된 지 가장 오래된 사진을 삭제한다.
  4. 현재 사진이 게시된 학생이 다른 학생의 추천을 받은 경우에는 추천받은 횟수만 증가시킨다.
  5. 사진틀에 게시된 사진이 삭제되는 경우에는 해당 학생이 추천받은 횟수는 0으로 바뀐다.

후보의 수 즉, 사진틀의 개수와 전체 학생의 추천 결과가 추천받은 순서대로 주어졌을 때, 최종 후보가 누구인지 결정하는 프로그램을 작성하시오.

 

입력

첫째 줄에는 사진틀의 개수 N이 주어진다. (1 ≤ N ≤ 20) 둘째 줄에는 전체 학생의 총 추천 횟수가 주어지고, 셋째 줄에는 추천받은 학생을 나타내는 번호가 빈 칸을 사이에 두고 추천받은 순서대로 주어진다. 총 추천 횟수는 1,000번 이하이며 학생을 나타내는 번호는 1부터 100까지의 자연수이다.

 

출력

사진틀에 사진이 게재된 최종 후보의 학생 번호를 증가하는 순서대로 출력한다.

 

예제

풀이 방법

전체 학생의 추천 결과가 추천받은 순서대로 주어졌을 때, 최종 후보의 학생 번호를 출력하는 문제였습니다.

 

먼저, 후보의 사진을 게시할 수 있는 규칙은

1) N개의 사진틀 중, 비어있는 사진 틀이 존재한다면 학생 사진 게시

2) 비어있는 사진 틀이 존재하지 않는다면

   i) 추천 받은 횟수가 가장 적은 학생 사진 삭제 후 추천 학생 사진 게시

   ii) 추천 받은 횟수가 같으면 게시된 지 가장 오래된 사진 삭제 후 추천 학생 사진 게시

단) 현재 사진이 게시된 학생이 추천을 받은 경우에는 횟수 증가

로 정리할 수 있습니다.

 

게시할 사진의 정보를 저장할 list를 이용하여 만약 list의 사이즈가 N개 보다 적을 경우에는 list안에 추천받은 학생의 정보가 있는지 확인 후, 만약 존재한다면 횟수를 +1 증가시키고, 정보가 없는 경우에는 list에 학생정보를 넣어주었습니다. 만약 비어있는 사진틀이 존재하지 않는다면 마찬가지로 list안에 추천받은 학생의 정보가 있는 경우에는 추천 횟수를 +1 증가시키고, 없는 경우에는 list 맨 앞에 있는 정보를 삭제 후, 추천받은 학생의 정보를 넣어주었습니다.

마지막으로 최종 후보의 학생 번호를 출력하기 위해, list에 들어가있는 학생의 번호를 answer 리스트에 넣어준 뒤, 학생 번호순으로 출력해주었습니다.

 

** 처음에 생각하지 못했던 부분이 비어있는 사진틀이 존재할 경우에 현재 사진이 게시된 학생인지 확인하지 않고 리스트에 넣어줘서 자꾸 틀렸습니다가 떴다.. 앞으로 생각좀하면서 문제풀어야지..

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
 
public class Main_BJ_1713_후보추천하기 {
    
    static class info implements Comparable<info>{
        int index, num, cnt;
 
        public info(int index, int num, int cnt) {
            super();
            this.index = index;
            this.num = num;
            this.cnt = cnt;
        }
 
        @Override
        public int compareTo(info o) {
            if(this.cnt==o.cnt) {
                return this.index-o.index;
            }
            return this.cnt-o.cnt;
        }
        
    }
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        StringBuilder sb = new StringBuilder();
        
        ArrayList<info> list = new ArrayList<>();
        ArrayList<Integer> answer = new ArrayList<>();
        
        int N = Integer.parseInt(br.readLine()); //사진 틀
        int M = Integer.parseInt(br.readLine()); //총 추천 횟수
        
        st = new StringTokenizer(br.readLine());
        for(int i=0;i<M;i++) {
            int student = Integer.parseInt(st.nextToken());
            if(list.size()<N) {
                boolean flag = false;
                for(int j=0;j<list.size();j++) {
                    if(list.get(j).num==student) {
                        list.get(j).cnt++;
                        flag = truebreak;
                    }
                }
                if(!flag) list.add(new info(i,student,1));
            }
            else {
                Collections.sort(list);
                boolean flag = false;
                for(int j=0;j<list.size();j++) {
                    if(list.get(j).num==student) {
                        list.get(j).cnt++;
                        flag = true;
                        break;
                    }
                }
                if(!flag) {
                    list.remove(0);
                    list.add(new info(i,student,1));
                }
            }
        }
        
        for(int i=0;i<list.size();i++) {
            answer.add(list.get(i).num);
        }
        
        Collections.sort(answer);
        
        for(int i=0;i<answer.size();i++) sb.append(answer.get(i)+" ");
        
        System.out.println(sb.toString());    
    }
 
}
cs

 

문제

생태학에서 나무의 분포도를 측정하는 것은 중요하다. 그러므로 당신은 미국 전역의 나무들이 주어졌을 때, 각 종이 전체에서 몇 %를 차지하는지 구하는 프로그램을 만들어야 한다.

 

입력

프로그램은 여러 줄로 이루어져 있으며, 한 줄에 하나의 나무 종 이름이 주어진다. 어떤 종 이름도 30글자를 넘지 않으며, 입력에는 최대 10,000개의 종이 주어지고 최대 1,000,000그루의 나무가 주어진다.

 

출력

주어진 각 종의 이름을 사전순으로 출력하고, 그 종이 차지하는 비율을 백분율로 소수점 4째자리까지 반올림해 함께 출력한다.

 

예제

 

풀이 방법

나무들이 주어졌을 때, 각 나무의 종이 전체에서 몇 %를 차지하는지 구하는 문제였습니다.

이 문제를 읽어봤을 때, HashMap을 이용해서 풀면 되겠구나 라는 생각을 먼저 했습니다. 나무의 종을 입력받고 만약 HashMap의 key 값에 tree가 포함되어 있지 않을 경우에는 같은 종이 없다는 의미므로 <tree 명, 1> 쌍의 <키, 값>을 HashMap에 넣어주었습니다. 반대로 이미 있는 경우에는 value값만 +1 해주었습니다. 나무를 다 입력받고 난 후, 사전 순으로 정렬하기 위해 ArrayList에 HashMap에 넣었던 데이터들을 넣어주고 정렬해주었습니다. 마지막으로 전체에서 얼마나 차지하는지를 구하기 위해 계산해주고 출력해주었습니다.

 

이 문제를 풀면서 NullPointer 런타임 에러가 발생했습니다.ㅠㅠㅠ 에러를 찾던 중, 32번 줄에서 발생한다는 것을 알고 수정했더니 통과할 수 있었습니다.ㅠㅠㅠㅠ

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
 
public class Main_BJ_4358_생태학 {
    
    static class info{
        String tree;
        int cnt;
        
        public info(String tree, int cnt) {
            this.tree = tree;
            this.cnt = cnt;
        }    
    }
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        HashMap<String, Integer> hm = new HashMap<String, Integer>();
        
        int count=0;
        while(true) {
            String tree = br.readLine();
            
            if(tree==null || tree.equals("")) break;
            count++;
            if(!hm.containsKey(tree)) hm.put(tree,1);
            else hm.put(tree, hm.get(tree)+1);
        }
        
        ArrayList<info> list = new ArrayList<>();
        Iterator<String> keys = hm.keySet().iterator();
        while(keys.hasNext()) {
            String tree1 = keys.next();
            list.add(new info(tree1,hm.get(tree1)));
        }
        
        Collections.sort(list, new Comparator<info>() {
 
            @Override
            public int compare(info o1, info o2) {
                return o1.tree.compareTo(o2.tree);
            }
        });
        
        for(int i=0;i<list.size();i++) {
            double per = (double)(list.get(i).cnt*100.0)/count;
            
            sb.append(list.get(i).tree+" "+String.format("%.4f", per)+"\n");
        }
        System.out.println(sb.toString());
    }
 
}
cs

 

문제

한윤정과 친구들은 이탈리아로 방학 여행을 갔다. 이탈리아는 덥다. 윤정이와 친구들은 아이스크림을 사먹기로 했다. 아이스크림 가게에는 N종류의 아이스크림이 있다. 모든 아이스크림은 1부터 N까지 번호가 매겨져있다. 어떤 종류의 아이스크림을 함께먹으면, 맛이 아주 형편없어진다. 따라서 윤정이는 이러한 경우를 피하면서 아이스크림을 3가지 선택하려고 한다. 이때, 선택하는 방법이 몇 가지인지 구하려고 한다.

 

입력

첫째 줄에 정수 N과 M이 주어진다. N은 아이스크림 종류의 수이고, M은 섞어먹으면 안 되는 조합의 개수이다. 아래 M개의 줄에는 섞어먹으면 안 되는 조합의 번호가 주어진다. 같은 조합은 두 번 이상 나오지 않는다. (1 ≤ N ≤ 200, 0 ≤ M ≤ 10,000)

 

출력

첫째 줄에, 가능한 방법이 총 몇 개 있는지 출력한다.

 

예제

 

풀이 방법

이 문제는 섞어먹으면 안 되는 조합을 피하면서 아이스크림을 3가지 선택하는 방법의 수를 구하는 문제였습니다.

먼저 피해야하는 조합의 번호인 값을 icecream 2차원 배열에 true로 표시해주었습니다. 그리고 난 후, 아이스크림 3가지를 선택하기 위해 조합을 이용한 뒤, 3가지를 모두 선택한 후, 이 아이스크림이 섞어먹어도 괜찮은 조합인지 판단하기 위해 isCheck() 메서드를 통해 확인해 주었습니다. 만약 고른 아이스크림 조합의 icecream 배열 값이 true인 경우에는 섞어먹으면 안 되는 조합이 포함되어있는 경우이므로 false를 리턴해주었습니다. 반대로 for문을 다 끝냈다면 이 아이스크림 조합은 섞어먹어도 괜찮은 조합이므로 true를 리턴해 선택하는 방법의 수인 ans값을 +1 해주었습니다. 모든 조합의 결과를 확인 한 뒤, 총 선택할 수 있는 방법의 수를 출력해주었습니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
 
public class Main_BJ_2242_한윤정이이탈리아에가서아이스크림을사먹는데 {
    
    static int N,M,ans=0;
    static boolean [][] icecream;
    static boolean [] visited;
    static int [] select;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        
        icecream = new boolean[N][N];
        visited = new boolean[N];
        select = new int[3];
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            int a = Integer.parseInt(st.nextToken())-1;
            int b = Integer.parseInt(st.nextToken())-1;
            
            icecream[a][b] = icecream[b][a] = true;
        }
        
        comb(0,0);
        System.out.println(ans);
 
    }
    
    public static void comb(int start,int cnt) {
        if(cnt==3) {
            if(isCheck()) ans++;
            return;
        }
        
        for(int i=start;i<N;i++) {
            if(!visited[i]) {
                visited[i] = true;
                select[cnt] = i;
                comb(i,cnt+1);
                visited[i] = false;
            }
        }
        
    }
    
    public static boolean isCheck() {
        for(int i=0;i<3;i++) {
            for(int j=i+1;j<3;j++) {
                if(icecream[select[i]][select[j]]) return false;
            }
        }
        return true;
    }
}
cs

 

 

'문제 > 백준' 카테고리의 다른 글

백준 1713번 후보 추천하기 [JAVA]  (1) 2021.07.04
백준 4358번 생태학 [JAVA]  (0) 2021.06.30
백준 1043번 거짓말 [JAVA]  (0) 2021.06.25
백준 2174번 로봇 시뮬레이션 [JAVA]  (0) 2021.06.25
백준 2252번 줄세우기 [JAVA]  (0) 2021.06.18

문제

지민이는 파티에 가서 이야기 하는 것을 좋아한다. 파티에 갈 때마다, 지민이는 지민이가 가장 좋아하는 이야기를 한다. 지민이는 그 이야기를 말할 때, 있는 그대로 진실로 말하거나 엄청나게 과장해서 말한다. 당연히 과장해서 이야기하는 것이 훨씬 더 재미있기 때문에, 되도록이면 과장해서 이야기하려고 한다. 하지만, 지민이는 거짓말쟁이로 알려지기는 싫어한다. 문제는 몇몇 사람들은 그 이야기의 진실을 안다는 것이다. 따라서 이런 사람들이 파티에 왔을 때는, 지민이는 진실을 이야기할 수 밖에 없다. 당연히, 어떤 사람이 어떤 파티에서는 진실을 듣고, 또다른 파티에서는 과장된 이야기를 들었을 때도 지민이는 거짓말쟁이로 알려지게 된다. 지민이는 이런 일을 모두 피해야 한다.

사람의 수 N이 주어진다. 그리고 그 이야기의 진실을 아는 사람이 주어진다. 그리고 각 파티에 오는 사람들의 번호가 주어진다. 지민이는 모든 파티에 참가해야 한다. 이때, 지민이가 거짓말쟁이로 알려지지 않으면서, 과장된 이야기를 할 수 있는 파티 개수의 최댓값을 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 사람의 수 N과 파티의 수 M이 주어진다.

둘째 줄에는 이야기의 진실을 아는 사람의 수와 번호가 주어진다. 진실을 아는 사람의 수가 먼저 주어지고 그 개수만큼 사람들의 번호가 주어진다. 사람들의 번호는 1부터 N까지의 수로 주어진다.

셋째 줄부터 M개의 줄에는 각 파티마다 오는 사람의 수와 번호가 같은 방식으로 주어진다.

N, M은 50 이하의 자연수이고, 진실을 아는 사람의 수와 각 파티마다 오는 사람의 수는 모두 0 이상 50 이하의 정수이다.

 

출력

첫째 줄에 문제의 정답을 출력한다.

 

예제

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_1043_거짓말 {
    
    static int N,M;
    static int [] truth;
    
    static ArrayList<Integer> party[], people[];
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken()); //사람 수
        M = Integer.parseInt(st.nextToken()); // 파티의 수
        
        truth = new int[N+1];
        
        people = new ArrayList[N+1];
        party = new ArrayList[M];
        
        for(int i=1;i<N+1;i++) people[i] = new ArrayList<>();
        for(int i=0;i<M;i++) party[i] = new ArrayList<>();
        
        st = new StringTokenizer(br.readLine());
        
        int know = Integer.parseInt(st.nextToken());
        for(int i=0;i<know;i++) {
            int num = Integer.parseInt(st.nextToken());
            truth[num]= -1;
        }
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            int person = Integer.parseInt(st.nextToken());
            for(int j=0;j<person;j++) {
                int num = Integer.parseInt(st.nextToken());
                party[i].add(num);
                people[num].add(i);
            }
        }
        
        isLie();
        
    }
 
    public static void isLie() {
        Queue<Integer> queue = new LinkedList<Integer>();
        boolean [] visited= new boolean[M];
        
        for(int i=1;i<N+1;i++) {
            if(truth[i]==-1) {
                for(int j=0;j<people[i].size();j++) {
                    if(!visited[people[i].get(j)]) {
                        queue.add(people[i].get(j));
                        visited[people[i].get(j)]=true;
                    }
                }
            }
        }
        
        while(!queue.isEmpty()) {
            int p = queue.poll();
            
             for(int i=0;i<party[p].size();i++) {
                 for(int j=0;j<people[party[p].get(i)].size();j++) {
                     if(!visited[people[party[p].get(i)].get(j)]) {
                         visited[people[party[p].get(i)].get(j)] = true;
                         queue.add(people[party[p].get(i)].get(j));
                     }
                 }
             }
        }
        int ans=0;
        for(int i=0;i<M;i++) {
            if(!visited[i]) {
                ans++;
            }
        }
        System.out.println(ans);
    }
}
cs

 

문제

가로 A(1≤A≤100), 세로 B(1≤B≤100) 크기의 땅이 있다. 이 땅 위에 로봇들이 N(1≤N≤100)개 있다.

로봇들의 초기 위치는 x좌표와 y좌표로 나타난다. 위의 그림에서 보듯 x좌표는 왼쪽부터, y좌표는 아래쪽부터 순서가 매겨진다. 또한 각 로봇은 맨 처음에 NWES 중 하나의 방향을 향해 서 있다. 초기에 서 있는 로봇들의 위치는 서로 다르다.

이러한 로봇들에 M(1≤M≤100)개의 명령을 내리려고 한다. 각각의 명령은 순차적으로 실행된다. 즉, 하나의 명령을 한 로봇에서 내렸으면, 그 명령이 완수될 때까지 그 로봇과 다른 모든 로봇에게 다른 명령을 내릴 수 없다. 각각의 로봇에 대해 수행하는 명령은 다음의 세 가지가 있다.

  1. L: 로봇이 향하고 있는 방향을 기준으로 왼쪽으로 90도 회전한다.
  2. R: 로봇이 향하고 있는 방향을 기준으로 오른쪽으로 90도 회전한다.
  3. F: 로봇이 향하고 있는 방향을 기준으로 앞으로 한 칸 움직인다.

간혹 로봇들에게 내리는 명령이 잘못될 수도 있기 때문에, 당신은 로봇들에게 명령을 내리기 전에 한 번 시뮬레이션을 해 보면서 안전성을 검증하려 한다. 이를 도와주는 프로그램을 작성하시오.

잘못된 명령에는 다음의 두 가지가 있을 수 있다.

  1. Robot X crashes into the wall: X번 로봇이 벽에 충돌하는 경우이다. 즉, 주어진 땅의 밖으로 벗어나는 경우가 된다.
  2. Robot X crashes into robot Y: X번 로봇이 움직이다가 Y번 로봇에 충돌하는 경우이다.

 

입력

첫째 줄에 두 정수 A, B가 주어진다. 다음 줄에는 두 정수 N, M이 주어진다. 다음 N개의 줄에는 각 로봇의 초기 위치(x, y좌표 순) 및 방향이 주어진다. 다음 M개의 줄에는 각 명령이 명령을 내리는 순서대로 주어진다. 각각의 명령은 명령을 내리는 로봇, 명령의 종류(위에 나와 있는), 명령의 반복 회수로 나타낸다. 각 명령의 반복 회수는 1이상 100이하이다.

 

 

출력

첫째 줄에 시뮬레이션 결과를 출력한다. 문제가 없는 경우에는 OK를, 그 외의 경우에는 위의 형식대로 출력을 한다. 만약 충돌이 여러 번 발생하는 경우에는 가장 먼저 발생하는 충돌을 출력하면 된다.

 

 

예제

 

풀이 방법

이 문제를 로봇들의 안정성을 검증하는 문제였습니다.

 

로봇이 수행할 수 있는 명령은 총 3가지로,

1) L : 로봇이 향하고 있는 방향을 기준으로 왼쪽으로 90도 회전

2) R : 로봇이 향하고 있는 방향을 기준으로 오른쪽으로 90도 회전

3) F : 로봇이 향하고 있는 방향을 기준으로 한 칸 이동 

 

먼저 로봇의 번호와 위치정보, 방향 정보를 list에 넣어두었습니다. 그리고 나서 M번의 명령을 통해 로봇들의 안정성을 검증할 수 있는데 move() 메서드를 이용해 움직일 로봇을 찾고, 명령에 따라 회전하거나 이동시켜 주었습니다. 만약 로봇이 움직였을 때,  그다음 움직일 위치가 벽에 충돌하는 경우 또는 다른 로봇과 충돌하는 경우에는 그 충돌을 출력해주고 종료해주었습니다. 반대로 로봇이 잘 움직였다면 그 마지막 위치의 정보를 다시 list에 넣어주고 다음 명령을 반복했습니다. M번의 로봇이 정상적으로 명령을 수행했다면 OK를 출력하고 종료해주었습니다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.StringTokenizer;
 
public class Main_BJ_2174_로봇시뮬레이션 {
    
    static class robot{
        int num ,x, y, dir;
 
        public robot(int num, int x, int y, int dir) {
            super();
            this.num = num;
            this.x = x;
            this.y = y;
            this.dir = dir;
        }
    }
    
    static int A,B,N,M;
    static int [][] map;
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
     
    static ArrayList<robot> list = new ArrayList<>();
    
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        A = Integer.parseInt(st.nextToken()); //가로
        B = Integer.parseInt(st.nextToken()); //세로
        
        map = new int[B][A];
        
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken()); //로봇수 
        M = Integer.parseInt(st.nextToken()); // 명령수
        
        int num=0;
        for(int i=1;i<=N;i++) {
            st = new StringTokenizer(br.readLine());
            int x = Integer.parseInt(st.nextToken())-1;
            int y = Integer.parseInt(st.nextToken())-1;
            String dir = st.nextToken();
            
            map[B-y-1][x] = i;
            if(dir.equals("N")) num=0;
            else if(dir.equals("E")) num=1;
            else if(dir.equals("S")) num=2;
            else if(dir.equals("W")) num=3;
            
            list.add(new robot(i,B-y-1,x,num));
        }
        
        for(int i=0;i<M;i++) {
            st = new StringTokenizer(br.readLine());
            int robot = Integer.parseInt(st.nextToken());
            String command = st.nextToken();
            int repetition = Integer.parseInt(st.nextToken());
            move(robot,command,repetition);    
        }
        
        System.out.println("OK");
 
    }
    
    public static void move(int robot, String command, int repetition) {
        
        for(int i=0;i<list.size();i++) {
            if(list.get(i).num==robot) { //움직일 로봇 찾고
                int direction = list.get(i).dir;
                if(command.equals("L")) { //왼쪽으로 90도
                    for(int j=0;j<repetition;j++) {
                        if(direction==0) direction=3;
                        else direction--;
                    }
                    list.set(i, new robot(list.get(i).num,list.get(i).x,list.get(i).y,direction));
                }else if(command.equals("R")) { //오른쪽으로 90도
                    for(int j=0;j<repetition;j++) {
                        if(direction==3) direction=0;
                        else direction++;
                    }
                    list.set(i, new robot(list.get(i).num,list.get(i).x,list.get(i).y,direction));
                }else if(command.equals("F")) { //현재 방향에서 한칸 앞으로
                    int x = list.get(i).x;
                    int y = list.get(i).y;
                    map[x][y] = 0;
                    int nx=0, ny=0;
                    for(int j=0;j<repetition;j++) {
                        nx = x+dx[direction];
                        ny = y+dy[direction];
                        
                        if(range(nx,ny)) {
                            if(map[nx][ny]==0) {
                                x = nx; y = ny;
                            }else {
                                System.out.println("Robot "+list.get(i).num+" crashes into robot "+map[nx][ny]);
                                System.exit(0);
                            }
                        }else {
                            System.out.println("Robot "+list.get(i).num+" crashes into the wall");
                            System.exit(0);
                        }
                    }
                    map[nx][ny] = list.get(i).num;
                    list.set(i, new robot(list.get(i).num,nx,ny,direction));
                }
            }
        }
        
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<&& y>=0 && y<A;
    }
 
}
cs

 

 

문제

N명의 학생들을 키 순서대로 줄을 세우려고 한다. 각 학생의 키를 직접 재서 정렬하면 간단하겠지만, 마땅한 방법이 없어서 두 학생의 키를 비교하는 방법을 사용하기로 하였다. 그나마도 모든 학생들을 다 비교해 본 것이 아니고, 일부 학생들의 키만을 비교해 보았다.

일부 학생들의 키를 비교한 결과가 주어졌을 때, 줄을 세우는 프로그램을 작성하시오.

 

입력

첫째 줄에 N(1 ≤ N ≤ 32,000), M(1 ≤ M ≤ 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의미이다.

학생들의 번호는 1번부터 N번이다.

 

출력

첫째 줄에 학생들을 키 순서대로 줄을 세운 결과를 출력한다. 답이 여러 가지인 경우에는 아무거나 출력한다.

 

예제

 

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
 
public class Main_BJ_2252_줄세우기 {
    
    
    static int N,M;
    static ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
    static int [] indegree;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        
        indegree = new int[N+1];
        
        for(int i=0;i<=N;i++) list.add(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());
            
            list.get(a).add(b);
            indegree[b]++;
        }
        sort();
    }
    
    public static void sort() {
        Queue<Integer> queue = new LinkedList<>();
        Queue<Integer> result = new LinkedList<>();
        
        for(int i=1;i<N+1;i++) {
            if(indegree[i]==0) {
                queue.add(i);
            }
        }
        
        while(!queue.isEmpty()) {
            int temp = queue.poll();
            result.add(temp);
            
            for(Integer item : list.get(temp)) {
                indegree[item]--;
                if(indegree[item]==0) {
                    queue.add(item);
                }
            }
        }
        while(!result.isEmpty()) {
            System.out.print(result.poll()+" ");
        }
    }
 
}
cs

 

'문제 > 백준' 카테고리의 다른 글

백준 1043번 거짓말 [JAVA]  (0) 2021.06.25
백준 2174번 로봇 시뮬레이션 [JAVA]  (0) 2021.06.25
백준 10282번 해킹 [JAVA]  (0) 2021.06.17
백준 19942 다이어트 [JAVA]  (0) 2021.06.16
백준 5014번 스타트링크 [JAVA]  (0) 2021.06.16

문제

최흉최악의 해커 yum3이 네트워크 시설의 한 컴퓨터를 해킹했다! 이제 서로에 의존하는 컴퓨터들은 점차 하나둘 전염되기 시작한다. 어떤 컴퓨터 a가 다른 컴퓨터 b에 의존한다면, b가 감염되면 그로부터 일정 시간 뒤 a도 감염되고 만다. 이때 b가 a를 의존하지 않는다면, a가 감염되더라도 b는 안전하다.

최흉최악의 해커 yum3이 해킹한 컴퓨터 번호와 각 의존성이 주어질 때, 해킹당한 컴퓨터까지 포함하여 총 몇 대의 컴퓨터가 감염되며 그에 걸리는 시간이 얼마인지 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 테스트 케이스의 개수가 주어진다. 테스트 케이스의 개수는 최대 100개이다. 각 테스트 케이스는 다음과 같이 이루어져 있다.

  • 첫째 줄에 컴퓨터 개수 n, 의존성 개수 d, 해킹당한 컴퓨터의 번호 c가 주어진다(1 ≤ n ≤ 10,000, 1 ≤ d ≤ 100,000, 1 ≤ c ≤ n).
  • 이어서 d개의 줄에 각 의존성을 나타내는 정수 a, b, s가 주어진다(1 ≤ a, b ≤ n, a ≠ b, 0 ≤ s ≤ 1,000). 이는 컴퓨터 a가 컴퓨터 b를 의존하며, 컴퓨터 b가 감염되면 s초 후 컴퓨터 a도 감염됨을 뜻한다.

각 테스트 케이스에서 같은 의존성 (a, b)가 두 번 이상 존재하지 않는다.

 

출력

각 테스트 케이스마다 한 줄에 걸쳐 총 감염되는 컴퓨터 수, 마지막 컴퓨터가 감염되기까지 걸리는 시간을 공백으로 구분지어 출력한다.

 

예제

 

풀이 방법

해커로부터 컴퓨터를 해킹해 서로 의존하는 컴퓨터들이 모두 감염되는 시간과, 감염된 컴퓨터의 수를 구하는 문제였습니다.

 

저는 배열과 리스트 두 가지 방식으로 다익스트라 알고리즘을 이용해 문제를 해결했습니다.

 

1) 연결되어 있는 컴퓨터 정보 배열/리스트에 저장

2) 컴퓨터간의 감염시간을 저장할 distance 배열 큰 수로 초기화

3) 다익스트라 알고리즘을 이용해 최소 감염시간 distance배열에 저장

4) 감염되는 시간 및 감염된 컴퓨터 수를 구하기 위해 distance배열 값이 INF가 아닌 경우 count++ 및 distance 최댓값 구하기

5) count 및 최대 distance 값 출력

 

코드 (배열)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
 
public class Main_BJ_10282_해킹_array {
    
    static class info{
        int end, time;
 
        public info(int end, int time) {
            super();
            this.end = end;
            this.time = time;
        }
 
    }
    
    static int INF = Integer.MAX_VALUE;
    static boolean[] visited;
    static List<info> list[];
    static int [] distance;
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc=0; tc<T;tc++) {
            st = new StringTokenizer(br.readLine());
            int n = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            
            list = new ArrayList[n+1];
            distance = new int[n+1];
            visited = new boolean[n+1];
            
            for(int i=1;i<=n;i++) list[i] = new ArrayList<>();
            
            for(int i=0;i<d;i++) {
                st = new StringTokenizer(br.readLine());
                int a = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
                int s = Integer.parseInt(st.nextToken());
                
                list[b].add(new info(a,s));
            }
            
            Arrays.fill(distance, INF);
            distance[c]=0;
            
            int min, current = 0;
            for(int i=0; i<n;i++) {
                min = Integer.MAX_VALUE;
                current = -1;
                for(int j=1;j<n+1;j++) {
                    if(!visited[j] && distance[j]<min) {
                        min = distance[j];
                        current =j;
                    }
                }
                if(current == -1break;
                
                for(info next : list[current]) {
                    if(!visited[next.end] && distance[next.end]> distance[current]+next.time) {
                        distance[next.end] = distance[current] + next.time;
                    }
                }
                visited[current] = true;
            }
            
            int count=0, max=0;
            for(int i=1;i<distance.length;i++) {
                if(distance[i]!=INF) {
                    count++;
                    max = Math.max(max, distance[i]);
                }
                
            }
            sb.append(count+" "+max+"\n");
        }
        System.out.println(sb.toString());
    }
 
}
cs

 

코드 (리스트)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_10282_해킹_list {
    
    static class info{
        int end, time;
 
        public info(int end, int time) {
            super();
            this.end = end;
            this.time = time;
        }
 
    }
    
    static int INF = Integer.MAX_VALUE;
    static boolean[] visited;
    static ArrayList<ArrayList<info>> list;
    static int [] distance;
    static PriorityQueue<info> pq = new PriorityQueue<>(new Comparator<info>() {
 
        @Override
        public int compare(info o1, info o2) {
            return o1.time-o2.time;
        }
    });
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        StringTokenizer st;
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc=0; tc<T;tc++) {
            st = new StringTokenizer(br.readLine());
            int n = Integer.parseInt(st.nextToken());
            int d = Integer.parseInt(st.nextToken());
            int c = Integer.parseInt(st.nextToken());
            
            list = new ArrayList<>();
            distance = new int[n+1];
            visited = new boolean[n+1];
            
            for(int i=0;i<=n;i++) list.add(new ArrayList<>());
            
            for(int i=0;i<d;i++) {
                st = new StringTokenizer(br.readLine());
                int a = Integer.parseInt(st.nextToken());
                int b = Integer.parseInt(st.nextToken());
                int s = Integer.parseInt(st.nextToken());
                
                list.get(b).add(new info(a,s));
            }
            
            Arrays.fill(distance, INF);
            
            distance[c]=0;
            
            pq.add(new info(c,0));
            while(!pq.isEmpty()) {
                info temp = pq.poll();
                if(visited[temp.end]) continue;
                visited[temp.end]= true;
                
                for(info node : list.get(temp.end)) {
                    if(distance[node.end]>distance[temp.end]+node.time) {
                        distance[node.end] = distance[temp.end]+node.time;
                        pq.add(new info(node.end,distance[node.end]));
                    }
                }
            }
            
            
            int count=0, max=0;
            for(int i=1;i<distance.length;i++) {
                if(distance[i]!=INF) {
                    count++;
                    max = Math.max(max, distance[i]);
                }
                
            }
            sb.append(count+" "+max+"\n");
        }
        System.out.println(sb.toString());
    }
 
}
cs

 

 

문제

식재료 N개 중에서 몇 개를 선택해서 이들의 영양분(단백질, 탄수화물, 지방, 비타민)이 일정 이상이 되어야 한다. 아래 표에 제시된 6가지의 식재료 중에서 몇 개를 선택해서 이들의 영양분의 각각 합이 최소 100, 70, 90, 10가 되도록 하는 경우를 생각해보자. 이 경우 모든 재료를 선택하면 쉽게 해결되지만, 우리는 조건을 만족시키면서도 비용이 최소가 되는 선택을 하려고 한다.

재료 단백질 지방 탄수화물 비타민 가격

1 30 55 10 8 100
2 60 10 10 2 70
3 10 80 50 0 50
4 40 30 30 8 60
5 60 10 70 2 120
6 20 70 50 4 40

예를 들어, 식재료 1, 3, 5를 선택하면 영양분은 100, 145, 130, 10으로 조건을 만족하지만 가격은 270이 된다. 대신 2, 3, 4를 선택하면 영양분의 합은 110, 130, 90, 10, 비용은 180이 되므로, 앞의 방법보다는 더 나은 선택이 된다.

입력으로 식재료 표가 주어졌을 때, 최저 영양소 기준을 만족하는 최소 비용의 식재료 집합을 찾아야 한다.

 

입력

첫 줄에 식재료의 개수 N이 주어진다.

다음 줄에는 단백질, 지방, 탄수화물, 비타민의 최소 영양성분을 나타내는 정수 mp, mf, ms, mv가 주어진다.

이어지는 N개의 각 줄에는 i번째 식재료의 단백질, 지방, 탄수화물, 비타민과 가격이 5개의 정수 pi, fi, si, vi, ci와 같이 주어진다. 식재료의 번호는 1부터 시작한다.

 

출력

첫 번째 줄에 최소 비용을 출력하고, 두 번째 줄에 조건을 만족하는 최소 비용 식재료의 번호를 공백으로 구분해 오름차순으로 한 줄에 출력한다. 같은 비용의 집합이 하나 이상이면 사전 순으로 가장 빠른 것을 출력한다.

조건을 만족하는 답이 없다면 -1을 출력하고, 둘째 줄에 아무것도 출력하지 않는다.

 

예제

 

풀이 방법

선택한 식재료들의 영양분 합이 최저 영양소 기준을 만족하면서 최소 비용의 식재료의 집합을 찾는 문제였습니다.

 

일단 먼저, 만족하는 집합을 찾기 위해 식재료를 최소 1개 이상 최대 N개 이하를 선택할 수 있기 때문에 반복문을 통해 해당 식재료 개수만큼 선택하여 그 선택된 식재료의 영양분 합이 최저 영양소의 기준을 만족하나 확인해 주었습니다.

isCheck() 메서드에서 선택한 식재료들의 영양분의 합들을 sum배열에 넣어준 뒤, 하나라도 최저 영양소 기준을 만족하지 못한다면 false를 리턴해주고 이외에는 선택된 식재료들의 가격을 비교하여 최소 비용의 식재료의 집합을 찾아주었습니다. 

 

출력 조건이 같은 비용의 집합이 하나 이상이면 사전 순으로 가장 빠른 것을 출력해야 하기 때문에, list에 넣어 정렬을 한 뒤 가장 첫 번째 리스트의 값을 출력해주었습니다. 만약 조건을 만족하는 집합이 없다면 -1을 출력해주었습니다. 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
 
public class Main_BJ_19942_다이어트 {
    
    static int N, M=5,ans =Integer.MAX_VALUE;
    static int [][] nutrients;
    static int [] minN;
    static int []select;
    
    static ArrayList<String> list = new ArrayList<>();
    
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        N = Integer.parseInt(br.readLine());
        
        nutrients = new int[N][M]; // N개의 영양분을 담을 배열
        minN = new int[4]; // 최저 영양소 기준을 담을 배열
        
        st = new StringTokenizer(br.readLine());
        for(int i=0;i<4;i++) minN[i] = Integer.parseInt(st.nextToken());
        
        for(int i=0;i<N;i++) {
            st = new StringTokenizer(br.readLine());
            for(int j=0;j<M;j++) {
                nutrients[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        for(int i=1;i<=N;i++) {
            select = new int[N];
            choice(0,i,0);
        }
        if(list.size()>0) {
            System.out.println(ans);
            Collections.sort(list);
            String st1 = list.get(0);
            for(int i=0;i<st1.length();i++) {
                System.out.print(st1.charAt(i));
            }
        }else System.out.println(-1);
    }
    
    public static void choice(int cnt, int sel, int start) {
        if(cnt==sel) {
           isCheck(sel); //조건체크
            return;
        }
        for(int i=start;i<N;i++) {
                select[cnt]=i;
                choice(cnt+1,sel,i+1);
        }
        
    }
    
    public static boolean isCheck(int sel) {
        int price=0;
        int []sum = new int[4];
        for(int i=0;i<sel;i++) {
                sum[0]+=nutrients[select[i]][0];
                sum[1]+=nutrients[select[i]][1];
                sum[2]+=nutrients[select[i]][2];
                sum[3]+=nutrients[select[i]][3];
                price+=nutrients[select[i]][4];            
        }
        
        for(int i=0;i<4;i++) {
            if(minN[i]>sum[i]) return false;
        }
        
        if(ans>=price) {
            if(ans>price) {
                list.clear();
            }
            String str="";
            for(int i=0;i<sel;i++) {
                str+=(select[i]+1+" ");
            }
            list.add(str);
            ans = price;
        }
        return true;
    }
}
cs

 

'문제 > 백준' 카테고리의 다른 글

백준 2252번 줄세우기 [JAVA]  (0) 2021.06.18
백준 10282번 해킹 [JAVA]  (0) 2021.06.17
백준 5014번 스타트링크 [JAVA]  (0) 2021.06.16
백준 9207번 페그 솔리테어 [JAVA]  (0) 2021.06.15
백준 17143번 낚시왕 [JAVA]  (0) 2021.06.15

문제

강호는 코딩 교육을 하는 스타트업 스타트링크에 지원했다. 오늘은 강호의 면접날이다. 하지만, 늦잠을 잔 강호는 스타트링크가 있는 건물에 늦게 도착하고 말았다.

스타트링크는 총 F층으로 이루어진 고층 건물에 사무실이 있고, 스타트링크가 있는 곳의 위치는 G층이다. 강호가 지금 있는 곳은 S층이고, 이제 엘리베이터를 타고 G층으로 이동하려고 한다.

보통 엘리베이터에는 어떤 층으로 이동할 수 있는 버튼이 있지만, 강호가 탄 엘리베이터는 버튼이 2개밖에 없다. U버튼은 위로 U층을 가는 버튼, D버튼은 아래로 D층을 가는 버튼이다. (만약, U층 위, 또는 D층 아래에 해당하는 층이 없을 때는, 엘리베이터는 움직이지 않는다)

강호가 G층에 도착하려면, 버튼을 적어도 몇 번 눌러야 하는지 구하는 프로그램을 작성하시오. 만약, 엘리베이터를 이용해서 G층에 갈 수 없다면, "use the stairs"를 출력한다.

 

입력

첫째 줄에 F, S, G, U, D가 주어진다. (1 ≤ S, G ≤ F ≤ 1000000, 0 ≤ U, D ≤ 1000000) 건물은 1층부터 시작하고, 가장 높은 층은 F층이다.

 

출력

첫째 줄에 강호가 S층에서 G층으로 가기 위해 눌러야 하는 버튼의 수의 최솟값을 출력한다. 만약, 엘리베이터로 이동할 수 없을 때는 "use the stairs"를 출력한다.

 

예제

 

풀이 방법

S층에서 G층으로 가기 위해 눌러야 하는 최소한의 버튼 수를 구하는 문제였습니다.

 

먼저 현재 위치를 우선순위 큐에 넣어주었습니다. 현재 위치가 도착 층수인 G층 이라면 우선순위 큐에 같이 넣어주었던 누른 버튼의 수를 출력하면서 반복문을 종료하고, 그 외에 경우에 위로 U층만큼, 아래로 D층만큼 이동하면서 만약 한 번도 도착하지 않았던 층수라면 도착했다고 표시해주고 큐에 해당 위치 정보를 넣어주었습니다. 만약 큐에 아무것도 없어 반복문이 종료되었고, 도착하고자 하는 층수에 도착했는지를 확인해주는 flag변수를 통해 flag가 false라면 도착 층수에 도달하지 못한다는 의미이므로 use the stairs를 출력해주었습니다.

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
 
public class Main_BJ_5014_스타트링크 {
    
    static class info implements Comparable<info>{
        int floor, check;
 
        public info(int floor, int check) {
            super();
            this.floor = floor;
            this.check = check;
        }
 
        @Override
        public int compareTo(info o) {
            return this.check-o.check;
        }
        
    }
    
    static int F,S,G,U,D;
    static int [] map;
    static PriorityQueue<info> queue = new PriorityQueue<>();
 
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st;
        
        st = new StringTokenizer(br.readLine());
        
        F = Integer.parseInt(st.nextToken()); //층 총수
        S = Integer.parseInt(st.nextToken()); // 현재 층수
        G = Integer.parseInt(st.nextToken()); // 도착 층수
        U = Integer.parseInt(st.nextToken()); //위로 U만큼
        D = Integer.parseInt(st.nextToken()); //아래로 D만큼
        
        map = new int[F+1];
        
        queue.add(new info(S,0));
        
        int [] dx = {U,-D};
        boolean flag = false;
        while(!queue.isEmpty()) {
            info now = queue.poll();
            
            
            if(now.floor==G) {
                flag=true;
                System.out.println(now.check);
                break;
            }
            
            for(int i=0;i<2;i++) {
                int nx = now.floor+dx[i];
                if(range(nx) && map[nx]==0) {
                    map[nx]=1;
                    queue.add(new info(nx,now.check+1));
                }
            }
        }
        if(!flag) System.out.println("use the stairs");
        
    }
    
    public static boolean range(int x) {
        return x>=1 && x<=F;
    }
 
}
cs

 

 

 

'문제 > 백준' 카테고리의 다른 글

백준 10282번 해킹 [JAVA]  (0) 2021.06.17
백준 19942 다이어트 [JAVA]  (0) 2021.06.16
백준 9207번 페그 솔리테어 [JAVA]  (0) 2021.06.15
백준 17143번 낚시왕 [JAVA]  (0) 2021.06.15
백준 16235번 나무 재테크 [JAVA]  (0) 2021.06.11

문제

페그 솔리테어는 구멍이 뚫려있는 이차원 게임판에서 하는 게임이다. 각 구멍에는 핀을 하나 꽂을 수 있다.

핀은 수평, 수직 방향으로 인접한 핀을 뛰어넘어서 그 핀의 다음 칸으로 이동하는 것만 허용된다. 인접한 핀의 다음 칸은 비어있어야 하고 그 인접한 핀은 제거된다.

현재 게임판에 꽂혀있는 핀의 상태가 주어진다. 이때, 핀을 적절히 움직여서 게임판에 남아있는 핀의 개수를 최소로 하려고 한다. 또, 그렇게 남기기 위해 필요한 최소 이동횟수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 테스트 케이스의 개수 1 ≤ N ≤ 100이 주어진다. 각 테스트 케이스는 게임판의 초기 상태이다.

게임판은 모두 같은 모양을 가진다. (예제 참고) '.'는 빈 칸, 'o'는 핀이 꽂혀있는 칸, '#'는 구멍이 없는 칸이다. 핀의 개수는 최대 8이며, 각 테스트 케이스는 빈 줄로 구분되어져 있다.

 

출력

각 테스트 케이스에 대해서, 핀을 움직여서 남길 수 있는 핀의 최소 개수와 그 개수를 만들기 위해 필요한 최소 이동 횟수를 출력한다.

 

예제

풀이 방법

핀을 적절히 움직여서 게임판에 남아있는 핀의 개수를 최소로하는 동시에, 최소로 남기기 위해 필요한 최소 이동 횟수를 구하는 문제였습니다. 

 

게임판의 존재하는 핀의 개수를 카운트해주고, remainPin 변수에 핀의 개수를 넣어주었습니다. 게임판의 해당 위치가 핀이 꽂혀있는 칸이라면 dfs() 메서드를 통해 현재 위치의 다음 위치가 게임판의 범위를 넘지 않으면서 핀이 꽂혀있는 칸이고 그 다다음 칸이 빈칸이라면 해당 위치의 핀을 이동할 수 있으므로, 이동시켜주고 핀의 개수를 하나 줄이고, 움직인 수를 하나 늘린 뒤, 다음 게임판에서 핀이 꽂혀있는 위치를 찾은 뒤 위에 과정을 반복해주었습니다. 과정이 끝난 후, 마지막으로 남아있는 핀의 개수와, 이동 횟수를 출력해주었습니다.

 

코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
 
public class Main_BJ_9207_페그솔리테어 {
    
    static char [][] map;
    static int xx=5,yy=9,remainPin, move;
    
    static int [] dx = {-1,0,1,0};
    static int [] dy = {0,1,0,-1};
 
    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
        
        int T = Integer.parseInt(br.readLine());
        
        for(int tc=0; tc<T;tc++) {
            map = new char[xx][yy];
            
            int pin=0;
            for(int i=0;i<xx;i++) {
                String str = br.readLine();
                for(int j=0;j<yy;j++) {
                    map[i][j] = str.charAt(j);
                    if(map[i][j]=='o') pin++;
                }
            }
            
            remainPin = pin;
            
            for(int i=0;i<xx;i++) {
                for(int j=0;j<yy;j++) {
                    if(map[i][j]=='o') dfs(i,j,pin,0);
                }
            }
            
            br.readLine();
            
            sb.append(remainPin+" "+move+"\n");
        }
        
        System.out.println(sb.toString());
 
    }
    
    public static void dfs(int x, int y , int remain, int moveCnt) {
        if(remain<=remainPin) {
            remainPin = remain;
            move = moveCnt;
        }
        
        for(int d=0;d<4;d++) {
            int nx = x + dx[d];
            int ny = y + dy[d];
            
            if(range(nx,ny) && map[nx][ny]=='o') {
                int nnx = nx +dx[d];
                int nny = ny +dy[d];
                
                if(range(nnx,nny) && map[nnx][nny]=='.') {
                    map[x][y]=map[nx][ny]='.';
                    map[nnx][nny]='o';
                    
                    for(int i=0;i<xx;i++) {
                        for(int j=0;j<yy;j++) {
                            if(map[i][j]=='o') dfs(i,j,remain-1,moveCnt+1);
                        }
                    }
                    
                    map[x][y]=map[nx][ny]='o';
                    map[nnx][nny]='.';
                }
            }
            
        }
    }
    
    public static boolean range(int x, int y) {
        return x>=0 && x<xx && y>=0 && y<yy;
    }
 
}
cs

+ Recent posts