https://www.acmicpc.net/problem/1107
문제
수빈이는 TV를 보고 있다. 수빈이는 채널을 돌리려고 했지만, 버튼을 너무 세게 누르는 바람에, 일부 숫자 버튼이 고장났다.
리모컨에는 버튼이 0부터 9까지 숫자, +와 -가 있다. +를 누르면 현재 보고있는 채널에서 +1된 채널로 이동하고, -를 누르면 -1된 채널로 이동한다. 채널 0에서 -를 누른 경우에는 채널이 변하지 않고, 채널은 무한대 만큼 있다.
수빈이가 지금 이동하려고 하는 채널은 N이다. 어떤 버튼이 고장났는지 주어졌을 때, 채널 N으로 이동하기 위해서 버튼을 최소 몇 번 눌러야하는지 구하는 프로그램을 작성하시오.
수빈이가 지금 보고 있는 채널은 100번이다.
입력
첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼이 주어지며, 같은 버튼이 여러 번 주어지는 경우는 없다.
출력
첫째 줄에 채널 N으로 이동하기 위해 버튼을 최소 몇 번 눌러야 하는지를 출력한다.
초기 풀이
처음에 BFS로, while문 안에서 queue의 원소 꺼내고, queue의 원소에 0~9 중 안 고장난 버튼 숫자 붙이거나 +1, -1하는 방식으로 풀려고 했다. 하지만 현재 채널에 도착했으면 거기에서 숫자를 붙일 수 없다(리모컨을 다들 써봐서 잘 알 것이다.). 따라서, 숫자를 붙여서 만들 수 있는 모든 숫자를 만들고, 거기에서 목적지까지의 거리를 구해야 한다. 다만, BFS로 가능한 숫자를 생성하면 '입력하여 도착한 100'을 구분하지 못하는 경우가 생길 수 있어, 구현에서 고려해주어야 한다.
풀이
브루트포스 방식으로 6자리 이하의 가능한 모든 숫자를 만든다. 이후, '|목적지-현재 숫자|+현재 숫자의 길이'가 가장 작은 값을 찾으면 된다. 또한, 100이 시작 채널이기에 '|목적지-100|'도 정답의 후보군이다.
유의할 점
1. 100에서도 시작하기에 찾아야 한다.
2. 찾는 채널은 50만 이하이지만, 50만 초과의 채널로 갈 수 있다.
3. 0도 가능한 채널이다.
4. 6자리 이하만 찾으면 되는 이유: 100에서 500000까지 +버튼을 누르면 499900번이 걸리는데, 100만 이상에서 500000까지는 최소 500007번이 걸리기 때문이다. 만약 문제의 N 범위가 0이상 700000 이하이고 가능한 숫자 버튼이 1뿐이라면, 1111111로 간 후 내려가는게 111111에서 올라가는거보다 빠를 것이다.
5. 이 외에도 많은 실수할만한 요소들이 있다: 열심히 풀고, 나름대로 디버깅도 했는데 '맞왜틀?'에 빠졌다면, 반례1, 반례2를 통해 잘 찾아보자.
배운 점
브루트포스 풀이의 코드를 보면 그렇게 어렵지 않다. 풀이 방법을 잘 파악할 필요가 있다.
SWEA 4311과 유사한 듯?
코드
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
|
import java.io.*;
import java.util.*;
public class Main {
static int ans = 1000000;
static boolean[] nums;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int M = Integer.parseInt(br.readLine());
nums = new boolean[10];
Arrays.fill(nums, true);
StringTokenizer st = null ;
if (M > 0) st = new StringTokenizer(br.readLine());
for (int i = 0; i < M; i++) {
nums[Integer.parseInt(st.nextToken())] = false;
}
ans = Math.abs(N-100);
for (int i = 0; i <= 9; i++) {
if (!nums[i]) continue;
dfs(i, N, 1);
}
System.out.println(ans);
}
static void dfs(int cur, int N, int len) {
if (len >= 7) return;
ans = Math.min(ans, Math.abs(N-cur) + len);
for (int i = 0; i <= 9; i++) {
if (!nums[i]) continue;
dfs(10*cur+i, N, len+1);
}
}
}
|
cs |
'PS > etc' 카테고리의 다른 글
벨만-포드 알고리즘 with 백준 11657번: 타임머신 (Java) (0) | 2022.07.25 |
---|---|
백준 1402번: 아무래도이문제는A번난이도인것같다 (Java) (0) | 2022.06.17 |
백준 15961번: 회전 초밥 (JAVA) (0) | 2022.04.05 |
백준: 제 1회 블롭컵 (앞 4문제만 JAVA 풀이) (0) | 2022.02.22 |
파이썬 사소한 팁 (0) | 2021.10.02 |