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

 

[난이도]

- Silver 3

 

[알고리즘]

- 백트래킹

 

[코드]

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

public class Main {
    static int N, num, min = Integer.MAX_VALUE;
    static int[] arr, list;
    static boolean[] visited;
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        String X = br.readLine();
        num = Integer.parseInt(X);
        N = X.length(); // 입력받은 문자열의 자릿수
        arr = new int[N];
        list = new int[N];
        visited = new boolean[N];
        for (int i = 0; i < N; i++) {
            arr[i] = X.charAt(i) - '0';
        }
        backTracking(0);
        System.out.println(min == Integer.MAX_VALUE ? 0 : min); // min이 여전히 Integer.MAX_VALUE 라면 0 출력 아니라면 min 출력
    }

    static void backTracking(int depth) {
        if (depth == N) {
            // int배열 -> 하나씩 꺼내서 하나의 문자열 -> 정수로 변환
            String s = "";
            for (int i : list) {
                s += i;
            }
            int n = Integer.parseInt(s);

            if (num < n) { // 입력값보다 큰 수중에 최솟값
                min = Math.min(min, n);
            }
            return;
        }
        for (int i = 0; i < N; i++) {
            if (!visited[i]) { // 사용하지 않은 숫자라면 사용
                visited[i] = true; // 사용한 숫자는 체크
                list[depth] = arr[i]; // 새로만들어지는 숫자는 list배열에 담아둠
                backTracking(depth + 1);
                visited[i] = false; // 사용 끝났으면 다시 false
            }
        }
    }
}

 

[풀이]

1. for문을 돌며 각 자리의 숫자를 list에 담아준 후 depth+1 시킨다.

2. depth 가 N이 되었다면 처음에 입력받은 숫자와 비교한다.

3. 비교한 수가 입력값보다 크다면 min을 갱신한다.

4. min이 갱신이안되었다면 0을출력 갱신되었다면 min 출력

 

for문을 돌며 list배열에 담아준것을 꺼내 비교하려면 

list배열에 담겨져있는 수를 하나의 문자열로 변환 후 문자열을 다시 정수로 변환해준다.

 // int배열 -> 하나씩 꺼내서 하나의 문자열 -> 정수로 변환
            String s = "";
            for (int i : list) {
                s += i;
            }
            int n = Integer.parseInt(s);

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

백준 15649: N과 M (1)[JAVA]  (0) 2024.05.07
백준 10974: 모든 순열[JAVA]  (0) 2024.05.04
백준 11060: 점프 점프[JAVA]  (0) 2024.05.03
백준 11060: 점프 점프[JAVA]  (1) 2024.05.02
백준 2644: 촌수계산[JAVA]  (0) 2024.05.02

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

 

[난이도]

- Silver 2

 

[알고리즘]

- BFS

 

[코드]

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

public class Main {
    static char[][] graph;
    static boolean[][] visited;
    static int T, H, W, answer = 0;
    static Queue<int[]> queue;
    static int[] dx = {-1, 1, 0, 0};
    static int[] dy = {-0, 0, -1, 1};
    static ArrayList<int[]> list;
    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(), " ");

        T = Integer.parseInt(st.nextToken());
        for (int i = 0; i < T; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            H = Integer.parseInt(st.nextToken());
            W = Integer.parseInt(st.nextToken());
            graph = new char[H][W];
            visited = new boolean[H][W];
            queue = new LinkedList<>();
            list = new ArrayList<>();
            answer = 0;
            for (int j = 0; j < H; j++) {
                String input = br.readLine();
                for (int k = 0; k < W; k++) {
                    graph[j][k] = input.charAt(k);
                }
            }
            for (int j = 0; j < H; j++) {
                for (int k = 0; k < W; k++) {
                    if (graph[j][k] == '#') { // 양일경우
                        if (!visited[j][k]) { // 방문하지 않은 곳일 경우 bfs 메서드 실행
                            queue.offer(new int[]{j, k});
                            visited[j][k] = true;
                            bfs();
                            answer++;
                        }
                    }
                }
            }
            bw.write(answer + "\n");

        }
        bw.flush();
        bw.close();
        br.close();
    }

    static void bfs() {
        while (!queue.isEmpty()) {
            int[] tmp = queue.poll();
            int x = tmp[0];
            int y = tmp[1];
            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i];
                int ny = y + dy[i];
                if (nx >= 0 && nx < H && ny >= 0 && ny < W) { // 인덱스 범위 안
                    if (graph[nx][ny] == '#') { // 양일 경우
                        if (!visited[nx][ny]) { // 방문하지 않은경우
                            visited[nx][ny] = true;
                            queue.offer(new int[]{nx, ny});
                        }
                    }
                }
            }
        }
    }
}

 

[풀이]

1. for문을 돌며 탐색한 위치가 양(#)이면서 체크하지않은 양일경우 bfs()를 실행하고 answer++한다.

2. bfs는 4방탐색을 하며 인덱스 범위 안이면서 양이면서 방문하지 않은 경우 새로 탐색한 위치를 큐에 담는다.

3. answer를 출력한다.

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

백준 10974: 모든 순열[JAVA]  (0) 2024.05.04
백준 2992: 크면서 작은 수[JAVA]  (0) 2024.05.04
백준 11060: 점프 점프[JAVA]  (1) 2024.05.02
백준 2644: 촌수계산[JAVA]  (0) 2024.05.02
백준 1012: 유기농 배추[JAVA]  (1) 2024.04.26

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

 

[난이도]

- Silver 2

 

[알고리즘]

- bfs

 

[코드]

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

public class Main {
    static int N;
    static int[] maze;
    static boolean[] visited;
    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());
        maze = new int[N];
        visited = new boolean[N];

        st = new StringTokenizer(br.readLine(), " ");
        for (int i = 0; i < N; i++) {
            maze[i] = Integer.parseInt(st.nextToken());
        }
        bfs();
    }
    static void bfs() {
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{0, 0});
        visited[0] = true;
        while (!queue.isEmpty()) {
            int[] tmp = queue.poll();
            int cur = tmp[0];
            int count = tmp[1];
            if (cur == N - 1) { // 도착했다면
                System.out.println(count); // count 출력
                return;
            }
            for (int i = 1; i <= maze[cur]; i++) {
                if (cur + i < N) { // 최대 인덱스를 넘어서지 않는 경우에만
                    if (!visited[cur + i]) { // 방문하지 않은 경우
                        queue.offer(new int[]{cur + i, count + 1});
                        visited[cur + i] = true;
                    }
                }
            }
        }
        System.out.println(-1); // 도착실패 시 출력
    }
}

 

[풀이]

DP로 풀 수 있는문제이다. 하지만 BFS로 풀었다.

1. 큐에 현재 위치와 몇번 점프했는지를 담는다.

2. 현재위치에서 이동가능한 만큼 반복하며 큐에 담는다. 큐에 담을때 이동했을 때의 위치와 현재까지 점프한 횟수 + 1를 해 큐에담는다.

이 때 이동했을 때의 위치가 최대 인덱스를 넘어서면 메모리초과가 발생하기 때문에 아닌경우에만 하고 방문하지 않은경우에만 큐에 담아준다.

3. 도착했다면 큐에담긴 count를 출력해주고 큐가 empty가 되어서 도착실패시 -1을 출력해준다.

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

 

[난이도]

- Silver 2

 

[알고리즘]

- bfs

 

[코드]

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

public class Main {
    static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
    static int[] dist;
    static boolean[] visited;
    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());
        dist = new int[n + 1];
        visited = new boolean[n + 1];

        st = new StringTokenizer(br.readLine(), " ");
        int p1 = Integer.parseInt(st.nextToken());
        int p2 = Integer.parseInt(st.nextToken());

        for (int i = 0; i <= n; i++) {
            graph.add(new ArrayList<>());
        }

        int m = Integer.parseInt(br.readLine());
        for (int i = 0; i < m; i++) {
            st = new StringTokenizer(br.readLine(), " ");
            int x = Integer.parseInt(st.nextToken());
            int y = Integer.parseInt(st.nextToken());
            graph.get(x).add(y);
            graph.get(y).add(x);
        }
        System.out.println(bfs(p1, p2));
    }

    static int bfs(int start, int end) {
        Queue<Integer> queue = new LinkedList<>();
        dist[start] = 0;
        visited[start] = true;
        queue.offer(start);
        while (!queue.isEmpty()) {
            int cur = queue.poll();
            for (int i = 0; i < graph.get(cur).size(); i++) {
                if (!visited[graph.get(cur).get(i)]) {
                    dist[graph.get(cur).get(i)] = dist[cur] + 1;
                    if (graph.get(cur).get(i) == end) {
                        return dist[graph.get(cur).get(i)];
                    }
                    queue.offer(graph.get(cur).get(i));
                    visited[graph.get(cur).get(i)] = true;
                }
            }
        }
        return -1;
    }
}

 

[풀이]

ArrayList<ArrayList<Integer>>를 활용해 가변적 배열처럼 사용한다. 

dist 배열은 p1기준으로 봤을때 각 사람의 촌수를 저장한다.

visited 배열은 이미 촌수를 계산했다면 다시 계산되면 안되기때문에 계산했는지 안했는지 체크하는 배열이다.

큐에 담긴 숫자를 꺼내 해당숫자와 연관이 있으면서 촌수를 계산하지 않은 숫자라면 큐에 꺼낸 숫자의 촌수 + 1을 연관되어있는 숫자에 기록해준다.

 

 

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

 

1012번: 유기농 배추

차세대 영농인 한나는 강원도 고랭지에서 유기농 배추를 재배하기로 하였다. 농약을 쓰지 않고 배추를 재배하려면 배추를 해충으로부터 보호하는 것이 중요하기 때문에, 한나는 해충 방지에 

www.acmicpc.net

 

 

[난이도]

- Silver 3

 

[알고리즘]

- bfs

 

[코드]

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

public class Main {
    static boolean[][] visited;
    static int[][] graph;
    static int N, M, answer = 0;

    static int[] dx = {-1, 1, 0, 0}; // 상, 하, 좌, 우
    static int[] dy = {0, 0, -1, 1};

    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 T = Integer.parseInt(st.nextToken());
        for (int i = 0; i < T; i++) { // T번 반복
            st = new StringTokenizer(br.readLine(), " ");
            N = Integer.parseInt(st.nextToken());
            M = Integer.parseInt(st.nextToken());
            int K = Integer.parseInt(st.nextToken());
            graph = new int[N][M];
            visited = new boolean[N][M];
            ArrayList<int[]> list = new ArrayList<>();
            answer = 0;
            for (int j = 0; j < K; j++) { // 양배추 K개의 위치
                st = new StringTokenizer(br.readLine(), " ");
                int X = Integer.parseInt(st.nextToken());
                int Y = Integer.parseInt(st.nextToken());
                graph[X][Y] = 1;
                if (graph[X][Y] == 1) {
                    list.add(new int[]{X, Y});
                }
            }
            for (int k = 0; k < list.size(); k++) {
                int[] tmp = list.get(k);
                int x = tmp[0];
                int y = tmp[1];
                if (!visited[x][y]) { // 이미 체크한 양배추가 아닐 경우에만 bfs메서드 실행
                    bfs(x, y);
                    answer++;
                }
            }
            System.out.println(answer);

        }
        bw.flush();
        bw.close();
        br.close();
    }

    static void bfs(int x, int y) {
        visited[x][y] = true;
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{x, y});
        while (!queue.isEmpty()) {
            int[] tmp = queue.poll();
            for (int i = 0; i < 4; i++) {
                int nx = tmp[0] + dx[i];
                int ny = tmp[1] + dy[i];
                if (nx >= 0 && nx < N && ny >= 0 && ny < M) {
                    if (graph[nx][ny] == 1) {
                        if (!visited[nx][ny]) {
                            visited[nx][ny] = true;
                            queue.offer(new int[]{nx, ny});
                        }
                    }
                }
            }
        }
    }
}

 

[풀이]

1. 각 양배추의 위치를 저장한다.

2. 방문하지 않은 양배추일 경우에는 bfs메서드를 실행한다.

3. bfs 메서드 : 4방탐색을 하며 양배추끼리 이어져있는지 확인한다.

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

백준 11060: 점프 점프[JAVA]  (1) 2024.05.02
백준 2644: 촌수계산[JAVA]  (0) 2024.05.02
백준 25418: 정수 a를 k로 만들기[JAVA]  (0) 2024.04.25
백준 2606: 바이러스[JAVA]  (0) 2024.04.25
백준 26876: New Time[JAVA]  (0) 2024.04.24

병렬화를 사용하면 여러 프로세스 또는 스레드를 동시에 실행하여 작업을 처리한다. 이렇게 함으로써 여러 프로세서 또는 코어를 활용하여 작업을 분산시키고 병렬적으로 실행함으로써 전체 작업을 효율적으로 처리할 수 있다. 하지만 스트림 병렬화는 절대 시도조차 하지 말자.

 

데이터 소스가 Stream.iterate 거나 중간 연산으로 limit을 쓰면 파이프라인 병렬화로는 성능 개선을 기대할 수 없다. Stream.iterate 메서드는 무한한 요소 시퀀스를 생성하므로 병렬 처리가 어렵다. 또한 limit 메서드는 요소의 수를 제한하기 때문에 요소를 나누어 병렬 처리하는 것이 어려워진다. 이러한 상황에서는 파이프라인 병렬화로 성능 향상을 기대하기 어렵다.

 

스트림을 잘못 병렬화하면 (응답 불가를 포함해) 성능이 나빠질 뿐만 아니라  결과 자체가 잘못되거나 예상 못한 동작이 발생할 수 있다.

 

조건일 잘 갖춰지면 병렬화해 프로세스 코어 수에 비례하는 성능 향상을 만들 수 있지만, 그런 조건은 없다고 봐도 될 것같다.(개인적인생각)

 

 

핵심 정리 : 계산도 올바로 수행하고 성능도 빨라질 거라는 확신 없이는 스트림 파이프라인 병렬화는 시도조차 하지 말라. 스트림을 잘못 병렬화하면 프로그램을 오동작하게 하거나 성능을 급격히 떨어뜨린다. 병렬화하는 편이 낫다고 믿더라도, 수정 후의 코드가 여전히 정확한지 확인하고 운영 환경과 유사한 조건에서 수행해보며 성능지표를 유심히 관찰하라. 그래서 계산도 정확하고 성능도 좋아졌음이 확실해졌을 때, 오직 그럴 때만 병렬화 버전 코드를 운영 코드에 반영하라.

 

그냥 스트림 병렬화는 하지말자.

컬렉션(Collection):

  • 일련의 객체를 저장하고 관리하는 자료구조.
  • 주요 컬렉션 인터페이스에는 List, Set, Queue 등이 있으며, 각각 ArrayList, LinkedList, HashSet, TreeSet, PriorityQueue 등의 구현체가 있다.
  • 컬렉션은 데이터를 저장하고 필요할 때 검색, 추가, 삭제 등의 작업을 수행할 수 있다.
  • 컬렉션은 데이터의 저장 순서가 보장될 수 있고, 중복된 요소를 허용할 수도 있다.

스트림(Stream):

  • 데이터를 처리하는 파이프라인 형태의 API.
  • 자료 처리 연산을 지원하며, 이를 이용하여 데이터를 필터링, 매핑, 정렬, 그룹화하는 등의 작업을 수행할 수 있다.
  • 스트림은 컬렉션, 배열, 파일 등의 데이터 소스에서 데이터를 가져와서 연속된 연산을 수행한다.
  • 스트림은 데이터 소스를 변경하지 않고, 중간 연산과 최종 연산으로 구성되어 있다.
  • 스트림은 데이터를 한 번만 처리할 수 있으며, 처리된 결과는 다시 스트림으로 반환되거나 최종 결과로 수집된다.

원소 시퀀스 : 데이터의 순서가 중요한 시퀀스 형태를 말한다. 이 시퀀스는 각각의 요소가 순서대로 나열되어 있으며, 각 요소는 고유한 위치(인덱스)를 가지고 있다. 대부분의 컬렉션과 배열은 원소 시퀀스로 간주될 수 있다.

 

Iterable : Java에서 컬렉션을 표현하기 위한 인터페이스다. 이 인터페이스는 컬렉션의 요소를 반복하는 데 사용된다.

 

핵심 정리 : 원소 시퀀스를 반환하는 메서드를 작성할 때는, 이를 스트림으로 처리하기를 원하는 사용자와 반복으로 처리하길 원하는 사용자가 모두 있을 수 있음을 떠올리고, 양쪽을 다 만족시키려 노력하자. 컬렉션을 반환할 수 있다면 그렇게 하라. 반환 전부터 이미 원소들을 컬렉션에 담아 관리하고 있거나 컬렉션을 하나 더 만들어도 될 정도로 원소 개수가 적다면 ArrayList 같은 표준 컬렉션 담아 반환하라. 그렇지 않으면 (반환할 시퀀스가 크지만 표현을 간결하게 할 수 있다면) 전용 컬렉션을 구현할지 고민하라. 컬렉션을 반환하는 게 불가능하면 스트림과 Iterable 중 더 자연스러운 것을 반환하라. 만약 나중에 Stream 인터페이스가 Iterable을 지원하도록 자바가 수정된다면, 그때는 안심하고 스트림을 반환하면 될 것이다(스트림 처리와 반복 모두에 사용할 수 있으니).

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

 

25418번: 정수 a를 k로 만들기

7(A), 8(연산 1), 9(연산 1), 18(연산 2), 19(연산 1), 38(연산 2), 76(연산 2), 77(연산 1)이 최소 연산이므로 정답은 7이다.

www.acmicpc.net

 

 

[난이도]

- Silver 3

 

[알고리즘]

- bfs

 

[코드]

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

public class Main {
    static int A, K, answer = Integer.MAX_VALUE;
    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(), " ");

        A = Integer.parseInt(st.nextToken());
        K = Integer.parseInt(st.nextToken());
        bfs();
    }
    static void bfs() {
        Queue<int[]> queue = new LinkedList<>();
        queue.offer(new int[]{A, 0});
        boolean[] visited = new boolean[K + 1];
        visited[A] = true;
        while (!queue.isEmpty()) {
            int tmp[] = queue.poll();
            if (tmp[0] == K) {
                System.out.println(tmp[1]);
                return;
            }
            // 연산 1과 연산 2를 둘다 시행한다
            if (tmp[0] * 2 <= K) { // 연산 2
                visited[tmp[0] * 2] = true;
                queue.offer(new int[]{tmp[0] * 2, tmp[1] + 1});
            }
            if (!visited[tmp[0] + 1]) { // 연산 1, // 연산 2로 수행한 수가 연산 1보다 더 적은 연산횟수이기 때문에 이미 연산 2로 수행한 수라면 패스
                queue.offer(new int[]{tmp[0] + 1, tmp[1] + 1});
            }
        }
    }
}

 

[풀이]

1. 연산 2와 연산 1을 둘다 시행한다.

2. 연산 2가 가능하다면 연산 2를 시행하고. 연산 후의 숫자를 true로 체크한다.

3. 연산 1은 연산 2로 수행한 수가 연산 1보다 무조건 더 적은 연산횟수를 가지기 때문에 이미 연산 2로 수행한 수라면(!visited[tmp[0])라면 패스

 

제대로 풀이방법이 떠오르지 않았다. 비슷한 문제를 푼적이 있는데 DP로 푸는방법이 훨씬 간단했던것같다.

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

백준 2644: 촌수계산[JAVA]  (0) 2024.05.02
백준 1012: 유기농 배추[JAVA]  (1) 2024.04.26
백준 2606: 바이러스[JAVA]  (0) 2024.04.25
백준 26876: New Time[JAVA]  (0) 2024.04.24
백준 2003: 수들의 합 2[JAVA]  (0) 2024.04.24

+ Recent posts