https://school.programmers.co.kr/learn/courses/30/lessons/64061

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

[시행 착오]

더보기
class Solution {
    public int solution(int[][] board, int[] moves) {
        int answer = 0;
        String basket = "0";
        for(int i=0;i<moves.length;i++){
            for(int j=0;j<board[0].length;j++){
                if(board[j][moves[i] - 1] != 0){
                    int tmp = board[j][moves[i] - 1];
                    board[j][moves[i] - 1] = 0;
                    if(basket.substring(basket.length()-1).equals(Integer.toString(tmp))){
                        answer+=2;
                        basket = basket.substring(0,basket.length()-1);
                        break;
                    } else {
                        basket += (String.valueOf(tmp));
                    }
                    break;
                }
            }
        }
        return answer;
    }
}

 

[정답 코드]

import java.util.*;

class Solution {
    public int solution(int[][] board, int[] moves) {
        int answer = 0;
        Stack<Integer> stack = new Stack<>();
        
        for(int i=0;i<moves.length;i++){
            for(int j=0;j<board.length;j++){
                if(board[j][moves[i]-1] != 0){
                    if(!stack.empty() && stack.peek() == board[j][moves[i]-1]){
                        answer+=2;
                        stack.pop();
                            board[j][moves[i]-1]=0;
                        break;
                    } else {
                        stack.push(board[j][moves[i]-1]);
                        board[j][moves[i]-1]=0;
                        break;
                    }
                } 
            }
        }     
        return answer;
    }
}

 

[설명]

이 문제는 시물레이션 문제로 보기에는 어려워 보이지만 생각보다 쉬운 문제라고 생각한다.

아이디어는 크레인이 인형을 뽑을 때마다 해당 위치에 가장 위에 쌓여있는 인형을 뽑은 후 해당 위치를 0 으로 변경해준다.

뽑은 인형은 stack에 담고, stack.peek() 함수를 사용해 stack의 가장 최근 숫자를 확인 후 뽑은 인형과 같다면 stack.pop()을 해 스택에서 제거해준다.

이론은 간단한데 처음에 틀렸던 이유는 스택을 사용하면 쉬운데 스택이 순간 생각나지 않아서 문자열로 풀다가 문제 일부분만 맞았었다. 문자열의 마지막숫자와 뽑은 인형을 비교해 나가는 로직이였는데 안되는 이유는 문제에서 인형의 번호가 0~100 까지 존재해 문자열의 마지막숫자로 비교하면 틀리게 되는것이였다. 

'코딩테스트' 카테고리의 다른 글

백준 2512번: 예산[JAVA]  (1) 2024.02.13
백준 1149번: RGB 거리[JAVA]  (1) 2024.02.05
백준 1463번: 1로 만들기[JAVA]  (0) 2024.02.02
백준 2839번: 설탕 배달[JAVA]  (1) 2024.02.02
백준 14503번: 로봇 청소기[JAVA]  (1) 2024.02.02

https://www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽

www.acmicpc.net

 

[정답 코드]

import java.io.*;
import java.util.*;

public class Main {
    static int N, M;
    static int[][] room;
    static int[] dx = {-1, 0, 1, 0};
    static int[] dy = {0, 1, 0, -1}; // 북, 동, 남, 서 순서
    static int count = 0;
    static boolean flag;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        st = new StringTokenizer(br.readLine(), " ");

        int robotX = Integer.parseInt(st.nextToken());
        int robotY = Integer.parseInt(st.nextToken());
        int robotHead = Integer.parseInt(st.nextToken());
        room = new int[N][M];

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            for (int j = 0; j < M; j++) {
                room[i][j] = Integer.parseInt(st.nextToken());
            }
        }
        clean(robotX, robotY, robotHead);
        System.out.println(count);
    }

    static void clean(int x, int y, int head) {
        // 현재 위치가 더럽다면 청소
        if (room[x][y] == 0) {
            room[x][y] = 2; // 현재 위치 청소
            count++;
        }
        flag = false;
        for (int i = 0; i < 4; i++) {
            int nextHead = (head + 3) % 4; // 반시계 방향으로 90도 회전한 방향이 청소할 구역인지
            int nextX = x + dx[nextHead];
            int nextY = y + dy[nextHead];
            if (nextX >= 0 && nextY >= 0 && nextX < N && nextY < M) {
                if (room[nextX][nextY] == 0) {
                    clean(nextX, nextY, nextHead);
                    flag = true; // 청소할 구역이 있는 경우
                    break;
                }
            }
            head = (head + 3) % 4; // 반시계 90도 회전
        }


        if (!flag) { // 네 방향이 모두 청소된곳이거나 벽인 경우
            int nextHead = (head + 2) % 4; // 후진
            int nextX = x + dx[nextHead];
            int nextY = y + dy[nextHead];
            if (nextX >= 0 && nextY >= 0 && nextX < N && nextY < M) { // 후진할 공간이 있을 경우
                if (room[nextX][nextY] != 1) {
                    clean(nextX, nextY, head); // 후진
                }
            }
        }
    }
}

 

[설명]

이 문제는 4방탐색을 활용한 구현문제이다.

문제 설명이 이상해 이해하기 어렵지만 간단하게 정리하자면

1. 현재 위치를 청소한다.

2. 바라보는 방향에서 반시계 90도로 회전하면 청소할 수 있는지 탐색한다.

3 - 1. 청소할 수 있다면 전진한다. 그 후 1번으로 간다.

3 - 2. 청소할 수 없다면 후진한다.

4 - 1. 후진할 수 있다면 1번으로 간다.

4 - 2. 후진할 수 없다면 종료한다.

 

먼저 방의 로봇청소기의 위치와 방향을 clean 함수에 넣고 실행시킨다.

clean 함수는 로봇청소기의 위치가 청소해야할곳이라면 청소를 해 해당 위치를 임의의 숫자 2로 변경해준다.

그 후 4방탐색을 실시하는데 중요한 점은 4방탐색을 할 때 내가 바라보는 방향에서 반시계로 90도 씩 돌아가는 순서대로 탐색을 해야하는 것이다.

(head + 3) % 4 를 했을 경우 내가 바라보는 방향 head에서 반시계로 90도 돌게된다. 그리고 이를 4번할 경우 다시 원래방향을 바라보게 된다.

예를들어 head 가 0(북쪽) 일경우

(0 + 3) % 4 = 3(서쪽)

(3 + 3) % 4 = 2(남쪽)

(2 + 3) % 4 = 1(동쪽)

(1 + 3) % 4 = 0(북쪽)

이렇게 네 방향을 탐색했는데 모두 청소된 곳이거나 벽일경우 

(head + 2) % 4 를 하게되면 180도 뒤를 바라보게 된다.

만약 head 가 0(북쪽) 일경우

(0 + 2) % 4 = 2(남쪽)

이므로 후진을 할 수 있다.

 

'코딩테스트' 카테고리의 다른 글

백준 1463번: 1로 만들기[JAVA]  (0) 2024.02.02
백준 2839번: 설탕 배달[JAVA]  (1) 2024.02.02
백준 13335번: 트럭[JAVA]  (1) 2024.02.01
백준 5212번: 지구 온난화[JAVA]  (1) 2024.02.01
백준 20310번: 타노스[JAVA]  (1) 2024.01.30

https://www.acmicpc.net/problem/13335

 

13335번: 트럭

입력 데이터는 표준입력을 사용한다. 입력은 두 줄로 이루어진다. 입력의 첫 번째 줄에는 세 개의 정수 n (1 ≤ n ≤ 1,000) , w (1 ≤ w ≤ 100) and L (10 ≤ L ≤ 1,000)이 주어지는데, n은 다리를 건너는 트

www.acmicpc.net

 

[정답 코드]

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        int n = Integer.parseInt(st.nextToken());
        int w = Integer.parseInt(st.nextToken());
        int L = Integer.parseInt(st.nextToken());

        Queue<Integer> truck = new LinkedList<>();
        Queue<Integer> bridge = new LinkedList<>();
        int count = 0;
        int bridgeWeight = 0;
        st = new StringTokenizer(br.readLine(), " ");

        for (int i = 0; i < n; i++) {
            truck.add(Integer.parseInt(st.nextToken())); // 트럭의 무게를 큐에 담음
        }

        for (int i = 0; i < w; i++) {
            bridge.add(0); // 현재 다리에 올라와있는 트럭의 무게
        }

        while (!bridge.isEmpty()) { // 현재 다리에 올라와 있는 트럭이 존재하지 않을 때 까지
            count++; // 로직이 진행될 때 마다 시간이 1씩 증가
            bridgeWeight-=bridge.poll(); // 다리에 올라와있는 트럭이 한대 씩 다리에서 내려옴 , queue.poll() : 큐의 맨 앞의 값 추출
            if (!truck.isEmpty()) { // 큐에 담긴 트럭이 존재하지 않을 때 까지
                if (truck.peek() + bridgeWeight <= L) { // 트럭큐에 담긴 맨앞의 값과 현재 다리위에 올라와있는 트럭의 무게의 합이 L 보다 낮을때 , queue.peek() : 큐의 맨 앞의 값 확인
                    bridgeWeight += truck.peek();
                    bridge.add(truck.poll()); // 다리에 한 대 씩 올라감
                } else {
                    bridge.add(0); // 트럭큐에 트럭이 존재하지만 다리의 최대하중 때문에 다리로 못올라갈 경우 truck.poll()은 하지 않는다.
                }
            }
        }
        System.out.println(count);

    }
}

 

[설명]

이 문제는 큐를 활용하면 쉽게 풀 수 있다. 먼저 다리위에 트럭이 몇개가 존재하는지를 담는 큐 bridge 를 하나 만들고, 다리를 건너기 전의 트럭을 담는 truck 큐를 하나 만들어준다.

bridge 큐가 빌때까지 반복한다. 반복문이 한번 반복될때마다 트럭이 다리위에서 한칸씩 전진하는 구조이다. 

한칸 전진할 때마다 truck 큐를 확인하며 truck 큐를 하나 꺼내 다리위에 올라갔을 때 최대하중을 넘는지 안넘는지 체크하고 넘지않는다면 bridge 큐에 넣고 넘는다면 bridge에 0을 집어 넣는다. 

https://www.acmicpc.net/problem/5212

 

5212번: 지구 온난화

첫째 줄에 지도의 크기 R과 C (1 ≤ R, C ≤ 10)가 주어진다. 다음 R개 줄에는 현재 지도가 주어진다.

www.acmicpc.net

 

 

[정답 코드]

import java.io.*;
import java.util.*;

public class Main {
    static int[] dx = {0, 0, 1, -1};
    static int[] dy = {1, -1, 0, 0};
    static char[][] graph; // 지도
    static int count; // 섬 근처의 바다의 수
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine(), " ");

        int R = Integer.parseInt(st.nextToken());
        int C = Integer.parseInt(st.nextToken());
        graph = new char[R][C];
        int up = R; // 지도의 가장 위
        int down = 0; // 지도의 가장 아래
        int left = C; // 지도의 가장 왼쪽
        int right = 0; // 지도의 가장 아래쪽

        for (int i = 0; i < R; i++) {
            String input = br.readLine();
            for (int j = 0; j < C; j++) {
                graph[i][j] = input.charAt(j);
            }
        }

        for (int i = 0; i < R; i++) {
            for (int j = 0; j < C; j++) {
                if (graph[i][j] == 'X') {
                    count = 0;
                    for (int k = 0; k < 4; k++) { // 우 좌 하 상 순서 4방 탐색
                        int nx = i + dx[k];
                        int ny = j + dy[k];
                        if (nx >= 0 && ny >= 0 && nx < R && ny < C) { // 지도 안에 있을경우
                            if (graph[nx][ny] == '.') { // 근처가 바다일 경우
                                count++;
                            }
                        } else { // 지도의 바깥부분도 바다
                            count++;
                        }
                    }
                    if (count >= 3) { // 바다가 3면 이상일 경우
                        graph[i][j] = 'S'; // 임의의 값 S 로 변경
                    }
                }
                if (graph[i][j] == 'X') { // 지도의 가장 위, 아래, 왼쪽, 오른쪽 의 좌표를 갱신
                    up = Math.min(up, i);
                    down = Math.max(down, i);
                    left = Math.min(left, j);
                    right = Math.max(right, j);
                }
            }
        }

        // 새로운 지도를 그려줌
        for (int i = up; i <= down; i++) {
            for (int j = left; j <= right; j++) {
                char c = graph[i][j];
                if (c == 'X') {
                    bw.write(c);
                } else {
                    bw.write('.');
                }
            }
            bw.write("\n");
        }
        bw.flush();
        bw.close();
        br.close();
    }
}

 

[설명]

4방탐색을 활용한 구현문제이다. 지도를 탐색하다가 섬을 만나면 4방탐색을 실시한다. 4방 탐색 dx/dy 기법을 활용해준다.

4방탐색을 하면서 바다의 수를  카운팅해 바다가 3면이상이면 섬을 지도에서 지워준다. 

지도를 탐색해 나아가면서 모든 섬의 좌표를 체크해 지도의 가장 위에 있는 섬, 아래있는 섬.. 등의 좌표를 갱신해 나간다.

탐색이 끝났다면 가장 바깥 부분의 섬의 좌표들을 활용해 새로운 지도를 그려준다.

'코딩테스트' 카테고리의 다른 글

백준 14503번: 로봇 청소기[JAVA]  (1) 2024.02.02
백준 13335번: 트럭[JAVA]  (1) 2024.02.01
백준 20310번: 타노스[JAVA]  (1) 2024.01.30
백준 19941번: 햄버거 분배[JAVA]  (0) 2024.01.29
백준 21921번: 블로그 [JAVA]  (0) 2024.01.28

+ Recent posts