문제

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.

만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다.

한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.

맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.

입력

첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.

출력

첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
2 초 192 MB 111468 28230 17526 22.739%

접근: 해당 문제는 최대 1000 * 1000 의 노드 수를 가질 수 있기 때문에 시간 초과가 나기 쉽다. 처음에는 visit을 나누어 생각하지 않아 틀린 답을 찾았다. 꼼꼼하게 문제 상황을 분석하는 것이 중요하다.

 

구현: map에서 특정 점에 도착했을 때 이전에 벽을 한번 부순 경우와 아직 부수지 않은 경우(cnt가 남아있는 경우)로 나누어서 visit 처리를 해야한다.

1) 3차원 배열로 벽을 부수기 전, 벽을 부순 후로 나누었다.

boolean visit[][][] = new boolean[2][n+1][m+1];

 

2)  BFS 내부 방문 조건은 다음과 같다.

        while (!queue.isEmpty()) {
            Info now = queue.poll();

            if (now.x == n && now.y == m) {
                return now.cost;
            }

            for (int i = 0; i < 4; i++) {
                int xx = now.x + mx[i];
                int yy = now.y + my[i];

                if (xx > 0 && xx <= n && yy > 0 && yy <= m) {

                    // 이미 방문한 경우
                    if(visit[now.cnt][xx][yy]) continue;

                    // 아직 방문하지 않았고 벽인 경우
                    if (map[xx][yy] == '1' && now.cnt == 1) {
                        visit[0][xx][yy] = true;
                        queue.add(new Info(xx, yy, 0, now.cost + 1));
                    }

                    // 벽이 아닌 경우는 cnt값을 유지하며 큐에 추가한다.
                    if (map[xx][yy] == '0') {
                        visit[now.cnt][xx][yy] = true;
                        queue.add(new Info(xx, yy, now.cnt, now.cost + 1));
                    }

                }
            }
        }

소스코드

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;

public class BOJ2206 {

    static int n,m;
    static char map[][];

    static int mx[] = {0, -1, 0, 1};
    static int my[] = {-1, 0, 1, 0};

    static int BFS(){

        Queue<Info> queue = new LinkedList<>();
        boolean visit[][][] = new boolean[2][n+1][m+1];

        visit[0][1][1] = true;
        visit[1][1][1] = true;

        queue.add(new Info(1, 1, 1, 1));

        while (!queue.isEmpty()) {
            Info now = queue.poll();

            if (now.x == n && now.y == m) {
                return now.cost;
            }

            for (int i = 0; i < 4; i++) {
                int xx = now.x + mx[i];
                int yy = now.y + my[i];

                if (xx > 0 && xx <= n && yy > 0 && yy <= m) {

                    // 이미 방문한 경우
                    if(visit[now.cnt][xx][yy]) continue;

                    // 아직 방문하지 않았고 벽인 경우
                    if (map[xx][yy] == '1' && now.cnt == 1) {
                        visit[0][xx][yy] = true;
                        queue.add(new Info(xx, yy, 0, now.cost + 1));
                    }

                    // 벽이 아닌 경우는 cnt값을 유지하며 큐에 추가한다.
                    if (map[xx][yy] == '0') {
                        visit[now.cnt][xx][yy] = true;
                        queue.add(new Info(xx, yy, now.cnt, now.cost + 1));
                    }

                }
            }
        }

        return -1;
    }




    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" ");

        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);

        map = new char[n + 1][m + 1];

        for (int i = 1; i <= n; i++) {

            char[] input = br.readLine().toCharArray();

            for (int j = 1; j <= m; j++) {
                map[i][j] = input[j - 1];
            }

        }

        int result = BFS();

        System.out.println(result);
  }

    static class Info{

        int x, y, cost;

        // 벽 부순 횟수
        int cnt;

        public Info(int x, int y, int cnt, int cost) {
            this.x = x;
            this.y = y;
            this.cnt = cnt;
            this.cost = cost;
        }
    }

}

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

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net


 

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

[ BOJ 1761 ] 정점들의 거리 ( JAVA )  (0) 2023.04.10
[ BOJ 1987 ] 알파벳 ( JAVA )  (0) 2023.04.05
[ BOJ 1162 ] 도로 포장 ( JAVA )  (0) 2023.03.30
[ BOJ 17404 ] RGB거리 2 ( JAVA )  (0) 2023.03.29
[ BOJ 12919 ] A와 B 2 ( JAVA )  (0) 2023.03.28

문제

준영이는 매일 서울에서 포천까지 출퇴근을 한다. 하지만 잠이 많은 준영이는 늦잠을 자 포천에 늦게 도착하기 일쑤다. 돈이 많은 준영이는 고민 끝에 K개의 도로를 포장하여 서울에서 포천까지 가는 시간을 단축하려 한다.

문제는 N개의 도시가 주어지고 그 사이 도로와 이 도로를 통과할 때 걸리는 시간이 주어졌을 때 최소 시간이 걸리도록 하는 K개의 이하의 도로를 포장하는 것이다. 도로는 이미 있는 도로만 포장할 수 있고, 포장하게 되면 도로를 지나는데 걸리는 시간이 0이 된다. 또한 편의상 서울은 1번 도시, 포천은 N번 도시라 하고 1번에서 N번까지 항상 갈 수 있는 데이터만 주어진다.

입력

첫 줄에는 도시의 수 N(1 ≤ N ≤ 10,000)과 도로의 수 M(1 ≤ M ≤ 50,000)과 포장할 도로의 수 K(1 ≤ K ≤ 20)가 공백으로 구분되어 주어진다. M개의 줄에 대해 도로가 연결하는 두 도시와 도로를 통과하는데 걸리는 시간이 주어진다. 도로들은 양방향 도로이며, 걸리는 시간은 1,000,000보다 작거나 같은 자연수이다.

출력

첫 줄에 K개 이하의 도로를 포장하여 얻을 수 있는 최소 시간을 출력한다.

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
2초 128 MB 13019 2756 1650 21.244%

접근 :  처음에는 n까지의 모든 경로를 구해서 각 경로마다 k개의 값을 구하여 총 값에서 빼는 방법을 생각했었다. 그러나 모든 경로를 구하는 것은 시간초과가 날 것이 분명했고 방법이 떠오르지 않아 다른 분들의 풀이를 조금 참고했다. 

문제는 DP와 다익스트라를 사용하여 i번째 도시로 가는 최단 거리와 포장한 도로의 수를 메모이제이션하여 해결하였다.

 

구현   

1) dist 배열 생성

  • 기존의 다익스트라와 달리 2차원 배열을 사용한다.
  • dist[ 도시번호 ][ 포장한 도로 수 ] 
// dist[i][j] i번째 도시를 방문 , 포장한 도로의 수 j
long dist[][] = new long[n+1][k+1];

for (int i = 1; i <= n; i++) {
    Arrays.fill(dist[i], INF);
}

2) 최단 거리 찾기

  • 다익스트라 알고리즘 구현
  • 도로를 포장하는 경우와 포장 하지 않는 경우를 고려하여 탐색을 진행한다.
while (!pq.isEmpty()) {
    Info now = pq.poll();

    if (dist[now.node][now.cnt] < now.cost) {
        continue;
    }

    for (Info next : map[now.node]) {

        // 포장 안 하는 경우 cnt 값을 그대로 유지하며 값이 더 작은 경우에만 노드를 넣는다.
        if (dist[next.node][now.cnt] > (now.cost + next.cost) ) {

            dist[next.node][now.cnt] = next.cost + now.cost;
            pq.add(new Info(next.node, now.cost + next.cost, now.cnt));

        }

        // 도로 포장을 하는 경우
        if ( (now.cnt < k) && (now.cost < dist[next.node][now.cnt + 1]) ) {

            dist[next.node][now.cnt + 1] = now.cost;
            pq.add(new Info(next.node, now.cost, now.cnt+1));

            }
        }
    }

내부 클래스  - 도로 포장 수를 저장하기 위해 cnt를 추가

static class Info{

    int node;
    long cost;
    int cnt;

    public Info(int node, long cost, int cnt) {
        this.node = node;
        this.cost = cost;
        this.cnt = cnt;
    }
}

제출 결과


소스코드

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * 도로 포장
 */
public class BOJ1162 {

    static int n, m, k;
    static List<Info> map[];

    static long INF = Long.MAX_VALUE;

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] input = br.readLine().split(" ");

        n = Integer.parseInt(input[0]);
        m = Integer.parseInt(input[1]);
        k = Integer.parseInt(input[2]);

        map = new ArrayList[n+1];

        for (int i = 1; i <= n; i++) {
            map[i] = new ArrayList<>();
        }

        for (int i = 0; i < m; i++) {
            int from, to , cost;
            String[] s = br.readLine().split(" ");

            from = Integer.parseInt(s[0]);
            to = Integer.parseInt(s[1]);
            cost = Integer.parseInt(s[2]);

            // 양방향 그래프 입력
            map[from].add(new Info(to, cost,0));
            map[to].add(new Info(from, cost, 0));
        }

        long result = dijkstra(1, n);

        System.out.println(result);
    }

    static long dijkstra(int start, int destination){

        PriorityQueue<Info> pq = new PriorityQueue<>(Comparator.comparingLong(i -> i.cost));

        // dist[i][j] i번째 도시를 방문 , 포장한 도로의 수 j
        long dist[][] = new long[n+1][k+1];

        for (int i = 1; i <= n; i++) {
            Arrays.fill(dist[i], INF);
        }

        dist[start][0] = 0;
        pq.add(new Info(start, 0, 0));


        while (!pq.isEmpty()) {
            Info now = pq.poll();

            if (dist[now.node][now.cnt] < now.cost) {
                continue;
            }

            for (Info next : map[now.node]) {

                // 포장 안 하는 경우 cnt 값을 그대로 유지하며 값이 더 작은 경우에만 탐색
                if (dist[next.node][now.cnt] > (now.cost + next.cost) ) {

                    dist[next.node][now.cnt] = next.cost + now.cost;
                    pq.add(new Info(next.node, now.cost + next.cost, now.cnt));

                }

                // 도로 포장을 하는 경우
                if ( (now.cnt < k) && (now.cost < dist[next.node][now.cnt + 1]) ) {

                    dist[next.node][now.cnt + 1] = now.cost;
                    pq.add(new Info(next.node, now.cost, now.cnt+1));

                    }
                }
            }

        long result = INF;

        for (Long v : dist[n]) {

            result = Math.min(v, result);
        }

        return result;
        }


    static class Info{

        int node;
        long cost;
        int cnt;

        public Info(int node, long cost, int cnt) {
            this.node = node;
            this.cost = cost;
            this.cnt = cnt;
        }
    }
}

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

 

1162번: 도로포장

첫 줄에는 도시의 수 N(1 ≤ N ≤ 10,000)과 도로의 수 M(1 ≤ M ≤ 50,000)과 포장할 도로의 수 K(1 ≤ K ≤ 20)가 공백으로 구분되어 주어진다. M개의 줄에 대해 도로가 연결하는 두 도시와 도로를 통과하

www.acmicpc.net


 

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

[ BOJ 1761 ] 정점들의 거리 ( JAVA )  (0) 2023.04.10
[ BOJ 1987 ] 알파벳 ( JAVA )  (0) 2023.04.05
[ BOJ 2206 ] 벽 부수고 이동하기 ( JAVA )  (0) 2023.04.03
[ BOJ 17404 ] RGB거리 2 ( JAVA )  (0) 2023.03.29
[ BOJ 12919 ] A와 B 2 ( JAVA )  (0) 2023.03.28

문제

RGB거리에는 집이 N개 있다. 거리는 선분으로 나타낼 수 있고, 1번 집부터 N번 집이 순서대로 있다.

집은 빨강, 초록, 파랑 중 하나의 색으로 칠해야 한다. 각각의 집을 빨강, 초록, 파랑으로 칠하는 비용이 주어졌을 때, 아래 규칙을 만족하면서 모든 집을 칠하는 비용의 최솟값을 구해보자.

  • 1번 집의 색은 2번, N번 집의 색과 같지 않아야 한다.
  • N번 집의 색은 N-1번, 1번 집의 색과 같지 않아야 한다.
  • i(2 ≤ i ≤ N-1)번 집의 색은 i-1, i+1번 집의 색과 같지 않아야 한다.

입력

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나 같은 자연수이다.

 

출력

첫째 줄에 모든 집을 칠하는 비용의 최솟값을 출력한다.

 

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
0.5 초 (추가 시간 없음) 128 MB 10491 6088 4990 58.084%

접근 :  RGB 거리 문제를 먼저 풀어보는 것을 권장한다. R,G,B 별로 각각 배열을 만들어야 한다. 즉, 기존 RGB 문제처럼 i(1 <= i <= N)번째 색칠한 집이 R인 경우, G인경우, B인 경우로 나누어 생각할 수 있다. 주어진 규칙에 따라 i번째 집을 R로 색칠하는 경우의 최소 비용은 i-1번째 집을 G, B로 색칠한 비용 중 최솟값 + R로 색칠하는 비용으로 나타낼 수 있다.

 

// i번째 집을 각각 색으로 칠하는 최소 비용을 구하는 점화식은 다음과 같다
dp_r[i] = Math.min( dp_g[i-1], dp_b[i-1] ) + cost_r[i];
dp_g[i] = Math.min( dp_r[i-1], dp_b[i-1] ) + cost_g[i];
dp_b[i] = Math.min( dp_g[i-1], dp_r[i-1] ) + cost_b[i];

 

 

이 점화식을 기본으로 두고, 주어진 첫번째 조건(1번 집의 색은 2번, N번 집의 색과 같지 않아야 한다.)을 만족하기 위해서는 1번 집을 어떤 색으로 칠했는지 알고 있어야 한다.

따라서 첫번째 집을 R로 칠하는 경우, G로 칠하는 경우, B로 칠하는 경우로 각각 나누어서 문제를 해결하였다.

 

구현   

 

1) dp 초깃값 갱신

  • 행번호에 따라 처음 집의 dp값을 지정
        // dp 초깃값 갱신
        // 0행: 1번째 집을 R로 색칠하는 경우이므로 다른 색으로 칠하는 비용은 INF로 처리
        dp_r[0][1] = dt[0][1];
        dp_g[0][1] = INF;
        dp_b[0][1] = INF;

        // G로 출발하는 경우
        dp_r[1][1] = INF;
        dp_g[1][1] = dt[1][1];
        dp_b[1][1] = INF;

        // B로 출발하는 경우
        dp_r[2][1] = INF;
        dp_g[2][1] = INF;
        dp_b[2][1] = dt[2][1];

2) 점화식 사용

  • 위에서 구한 점화식을 이용하여 n-1 번 집까지의 최소 색칠 비용을 구함
            // 기본 점화식을 사용하여 n-1번 집까지의 최소 색칠 비용을 구함
            for (int j = 2; j <= n - 1; j++) {

                dp_r[i][j] = Math.min(dp_g[i][j - 1], dp_b[i][j - 1]) + dt[0][j];
                dp_g[i][j] = Math.min(dp_r[i][j - 1], dp_b[i][j - 1]) + dt[1][j];
                dp_b[i][j] = Math.min(dp_g[i][j - 1], dp_r[i][j - 1]) + dt[2][j];

            }

 

 

 

  • 1번 집의 색( 행 번호)를 고려하여 n번째 집의 최소 색칠 비용을 구함
            // 마지막 n번째 집을 색칠할 때는 1번 집의 색(2차원 배열의 행)을 고려해 같은 색인 경우 INF로 처리함
            dp_r[i][n] = Math.min(dp_g[i][n - 1], dp_b[i][n - 1]) + ((i == 0) ? INF : dt[0][n]);
            dp_g[i][n] = Math.min(dp_r[i][n - 1], dp_b[i][n - 1]) + ((i == 1) ? INF : dt[1][n]);
            dp_b[i][n] = Math.min(dp_g[i][n - 1], dp_r[i][n - 1]) + ((i == 2) ? INF : dt[2][n]);

제출 결과


소스코드

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * RGB거리 2
 */

public class BOJ17404 {


    static int dp_r[][], dp_g[][], dp_b[][];
    static int n;

    static final int INF = 10000000;

    public static void main(String[] args) throws IOException {

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(bufferedReader.readLine());

        // 2차원 배열의 각각 행은 1번 집을 어떤 색으로 칠했는지를 나타낸다.
        // 즉, 0행은 R, 1행은 G, 2행은 B로 1번 집을 색칠했다는 것이다.
        dp_r = new int[3][n+1];
        dp_g = new int[3][n+1];
        dp_b = new int[3][n+1];

        // 칠하는 비용으로 0행은 R, 1행은 G, 2행은 B로 칠하는 비용을 저장
        int[][] dt = new int[3][n+1];

        for (int i = 1; i <= n; i++) {
            String[] s = bufferedReader.readLine().split(" ");

            dt[0][i] = Integer.parseInt(s[0]); // R로 칠하는 비용
            dt[1][i] = Integer.parseInt(s[1]); // G로 칠하는 비용
            dt[2][i] = Integer.parseInt(s[2]); // B로 칠하는 비용
        }

        
        // dp 초깃값 갱신
        // 0행: 1번째 집을 R로 색칠하는 경우이므로 다른 색으로 칠하는 비용은 INF로 처리
        dp_r[0][1] = dt[0][1];
        dp_g[0][1] = INF;
        dp_b[0][1] = INF;

        // G로 출발하는 경우
        dp_r[1][1] = INF;
        dp_g[1][1] = dt[1][1];
        dp_b[1][1] = INF;

        // B로 출발하는 경우
        dp_r[2][1] = INF;
        dp_g[2][1] = INF;
        dp_b[2][1] = dt[2][1];


        int result = INF;


        for (int i = 0; i < 3; i++) {

            // 기본 점화식을 사용하여 n-1번 집까지의 최소 색칠 비용을 구함
            for (int j = 2; j <= n - 1; j++) {

                dp_r[i][j] = Math.min(dp_g[i][j - 1], dp_b[i][j - 1]) + dt[0][j];
                dp_g[i][j] = Math.min(dp_r[i][j - 1], dp_b[i][j - 1]) + dt[1][j];
                dp_b[i][j] = Math.min(dp_g[i][j - 1], dp_r[i][j - 1]) + dt[2][j];

            }

            // 마지막 n번째 집을 색칠할 때는 1번 집의 색(2차원 배열의 행)을 고려해 같은 색인 경우 INF로 처리함
            dp_r[i][n] = Math.min(dp_g[i][n - 1], dp_b[i][n - 1]) + ((i == 0) ? INF : dt[0][n]);
            dp_g[i][n] = Math.min(dp_r[i][n - 1], dp_b[i][n - 1]) + ((i == 1) ? INF : dt[1][n]);
            dp_b[i][n] = Math.min(dp_g[i][n - 1], dp_r[i][n - 1]) + ((i == 2) ? INF : dt[2][n]);

            // 최솟값 구하기
            result = Math.min(result, Math.min(dp_r[i][n], Math.min(dp_g[i][n], dp_b[i][n])));
        }

        // 결과 출력
        System.out.println(result);
    }


}

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

 

17404번: RGB거리 2

첫째 줄에 집의 수 N(2 ≤ N ≤ 1,000)이 주어진다. 둘째 줄부터 N개의 줄에는 각 집을 빨강, 초록, 파랑으로 칠하는 비용이 1번 집부터 한 줄에 하나씩 주어진다. 집을 칠하는 비용은 1,000보다 작거나

www.acmicpc.net


 

문제

수빈이는 A와 B로만 이루어진 영어 단어 존재한다는 사실에 놀랐다. 대표적인 예로 AB (Abdominal의 약자), BAA (양의 울음 소리), AA (용암의 종류), ABBA (스웨덴 팝 그룹)이 있다.

이런 사실에 놀란 수빈이는 간단한 게임을 만들기로 했다. 두 문자열 S와 T가 주어졌을 때, S를 T로 바꾸는 게임이다. 문자열을 바꿀 때는 다음과 같은 두 가지 연산만 가능하다.

  • 문자열의 뒤에 A를 추가한다.
  • 문자열의 뒤에 B를 추가하고 문자열을 뒤집는다.

주어진 조건을 이용해서 S를 T로 만들 수 있는지 없는지 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 S가 둘째 줄에 T가 주어진다. (1 ≤ S의 길이 ≤ 49, 2 ≤ T의 길이 ≤ 50, S의 길이 < T의 길이)

출력

S를 T로 바꿀 수 있으면 1을 없으면 0을 출력한다.

 

시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
2 초 512 MB 6530 2162 1732 32.392%

구현 :  어떤 문자에 주어진 연산을 수행하면 T가 된다. 이 점을 이용하여 역으로 T에서 문자를 하나씩 줄이는 연산을 수행하였고 T가 될 수 있는 문자열들을 하나씩 찾으면서 S가 이에 해당하는지 판단하였다.

 

T를 기준으로 역으로 수행하는 연산은 다음과 같다.

  • (1) 문자열의 마지막 문자인 'A'를 지운다.
  • (2) 문자열의 첫번째 문자인 'B'를 지우고 문자열을 뒤집는다.

1) T의 첫번째 문자가 'A'인 경우

  • 어떤 문자열을 바꿨을 때 첫번째 문자가 'A'인 경우 마지막 문자에는 반드시 'A'가 와야한다
    ( 'B'가 오는 경우 문자가 뒤집어져서 맨 뒤에는 'B'가 위치할 수 없게 됨 )
        // 1 ) 첫 문자가 'A'인 경우
        if (now.charAt(0) == 'A')
        {
            // 'A'로 시작하고 'B'로 끝나는 문자열은 만들 수 없으므로 탐색 종료
            if (now.charAt(now.length() - 1) == 'B')
                return;
            // 가장 뒤에 추가된 'A'를 제외
            back( now.substring(0, now.length()-1) );
        }

 

2) T의 첫번째 문자가 'B'인 경우 ( 이 경우는 먼저 두 가지로 경우의 수가 나뉜다 ) 

  • T의 마지막 문자가 'B'인 경우 :  (2) 연산을 수행한다.
  • T의 마지막 문자가 'A'인 경우: 'A'가 마지막에 추가된 경우와, 'B'가 마지막에 추가된 경우가 있으므로 (1)(2) 연산을 모두 수행한다.

 

        else // if(now.charAt(0) =='B') 2) 첫 문자가 'B'인 경우
        {
            // 가장 마지막 문자가 'B'인 경우 앞에서 B를 제거하고 뒤집는다.
            if (now.charAt(now.length() - 1) == 'B') {
                sb = new StringBuilder( now.substring(1, now.length()) );
                back( sb.reverse().toString() );
            }
            else // if (now.length() -1 == 'A')
            {
                sb = new StringBuilder( now.substring(1, now.length()) );

                // 'B'가 마지막에 추가되어 뒤집어졌거나 'A'가 마지막에 추가된 경우
                back( sb.reverse().toString() );
                back( now.substring(0, now.length() - 1) );
            }
        }

제출 결과


소스코드

더보기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * A와 B 2
 */
public class BOJ12919 {

    static String S, T;
    static StringBuilder sb;
    
    static int length;

    static boolean equal = false;
    static void back(String now){

        // 탐색 종료 조건
        if (equal || now.length() <= length) {

            if (now.hashCode() == S.hashCode())
                equal = true;
            return;
        }
        
        // 1 ) 첫 문자가 'A'인 경우
        if (now.charAt(0) == 'A')
        {
            // 'A'로 시작하고 'B'로 끝나는 문자열은 만들 수 없으므로 탐색 종료
            if (now.charAt(now.length() - 1) == 'B')
                return;
            // 가장 뒤에 추가된 'A'를 제외
            back( now.substring(0, now.length()-1) );
        }
        else // if(now.charAt(0) =='B') 2) 첫 문자가 'B'인 경우
        {
            // 가장 마지막 문자가 'B'인 경우 앞에서 B를 제거하고 뒤집는다.
            if (now.charAt(now.length() - 1) == 'B') {
                sb = new StringBuilder( now.substring(1, now.length()) );
                back( sb.reverse().toString() );
            }
            else // if (now.length() -1 == 'A')
            {
                sb = new StringBuilder( now.substring(1, now.length()) );

                // 'B'가 마지막에 추가되어 뒤집어졌거나 'A'가 마지막에 추가된 경우
                back( sb.reverse().toString() );
                back( now.substring(0, now.length() - 1) );
            }
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        S = bufferedReader.readLine();
        T = bufferedReader.readLine();
        length = S.length();

        back(T);

        if (equal)
            System.out.println(1);
        else
            System.out.println(0);
    }

}

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

 

12919번: A와 B 2

수빈이는 A와 B로만 이루어진 영어 단어 존재한다는 사실에 놀랐다. 대표적인 예로 AB (Abdominal의 약자), BAA (양의 울음 소리), AA (용암의 종류), ABBA (스웨덴 팝 그룹)이 있다. 이런 사실에 놀란 수빈

www.acmicpc.net


 

+ Recent posts