mang_dev
맹꽁거리는 개발자
mang_dev
전체 방문자
오늘
어제
  • 분류 전체보기 (185)
    • Frontend (2)
      • Next.js (1)
    • Backend (3)
      • GraphQL (2)
    • Book (1)
      • 기타 (1)
    • Old (177)
      • 알고리즘 퍼즐 (1)
      • 백준 (131)
      • 프로그래머스 (0)
      • Codility (15)
      • LeetCode (7)
      • Codewars (1)
      • Codeforces (0)
      • Django (6)
      • React (2)
      • Naver Map Api (3)
      • Web UI (4)
      • Introduction to Cloud (2)
hELLO · Designed By 정상우.
mang_dev

맹꽁거리는 개발자

백준 16397번 탈출 // C++
Old/백준

백준 16397번 탈출 // C++

2020. 3. 18. 22:05

문제

 

홍익이는 홍익대학교 프로그래밍 경진대회의 출제진이다. 홍익이는 새벽에 문제를 만들던 도중 뒤통수에 느껴지는 고통과 함께 정신을 잃었다.

홍익이는 좁은 방에서 눈을 떴다. 주변을 살펴보니 벽면에는 LED로 된 다섯 자리 십진수 N이, 그 옆에 T, G라는 알파벳과 함께 또 다른 정수 두 개가 쓰여 있었고, 벽 앞에는 버튼 A, B 두 개가 있었다.

버튼을 이리저리 눌러보던 똑똑한 홍익이는 어떻게 해야 방을 탈출할 수 있을지 금방 눈치챘다.

버튼과 수에 대해 홍익이가 알아낸 것은 다음과 같다.

  1. 버튼 A를 누르면 N이 1 증가한다.
  2. 버튼 B를 누르면 N에 2가 곱해진 뒤, 0이 아닌 가장 높은 자릿수의 숫자가 1 줄어든다. 예를 들어 123→146으로, 5→0으로, 3→5로 변한다. 단, N이 0이면 버튼 B를 눌러도 수가 변하지 않는다.
  3. LED가 다섯 자리까지밖에 없기 때문에 N이 99,999를 넘어가는 순간 탈출에 실패하게 된다.
  4. 버튼 B를 눌러 N에 2를 곱한 순간 수가 99,999를 넘어간다면, 높은 자릿수의 수를 1 낮췄을때 99,999를 넘지 않는다고 해도 탈출에 실패하게 된다.

또한 홍익이는 최대 T회 버튼을 누를 수 있고, 그 횟수 안에 LED로 표현된 N을 G와 같게 만들어야 탈출할 수 있다는 사실을 알아냈다.

똑똑한 홍익이는 이와중에 자존심이 발동해 버튼 누르는 횟수를 최소로 하여 방을 탈출하기로 했다.

홍익이의 방 탈출을 기원하며, 탈출에 필요한 최소의 버튼 횟수를 구하자.

입력

첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다.

각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이 만들어야 하는 수를 뜻한다.

출력

첫 번째 줄에 탈출에 필요한 최소의 버튼 횟수를 출력한다.

만약 탈출할 수 없다면 “ANG”을 따옴표 없이 출력한다.

 


 

풀이

 

BFS를 이용하여 해당 수까지 몇 번만에 도달할 수 있는지를 구하면 된다.

 

버튼 A의 경우에는 N + 1이 99,999 이하라면 이동이 가능하다.

 

버튼 B의 경우에는 N * 2가 99,999 이하라면 이동이 가능한데, 이 때 N * 2에서 가장 큰 차수의 수를 1 감소한 값으로 이동한다.

 

이 부분을 cmath 헤더 파일 내의 log10 함수를 이용하여 구현하였다.

 

log10(n)을 int로 형 변환해준 수를 X라고 하자. 이 때, pow 함수를 이용하여 pow(10,X)를 N * 2에서 빼주면 된다.

 


 

코드

더보기
#include <iostream>
#include <string>
#include <queue>
#include <cmath>

using namespace std;

int N, T, G;

void input();
int solve();

queue<pair<int, int>> q; // 현재 숫자, 횟수
bool visit[100000] = { false, };

int main() {

	int res = solve();

	if (res == -1)
		cout << "ANG\n";
	else
		cout << res << "\n";

	return 0;
}

void input() {
	cin >> N >> T >> G;

	visit[N] = true;
	q.push(make_pair(N, 0));
}

int solve() {
	input();

	while (!q.empty()) {
		int cur = q.front().first;
		int count = q.front().second;
		q.pop();

		if (count > T)
			continue;

		if (cur == G)
			return count;

		if (cur + 1 <= 99999 && !visit[cur+1]) {
			q.push(make_pair(cur + 1, count + 1));
			visit[cur + 1] = true;
		}

		if (cur * 2 <= 99999) {
			int minus = pow(10, (int)log10(cur * 2));
			int next = cur * 2 - minus;
			if (!visit[next]) {
				q.push(make_pair(next, count + 1));
				visit[next] = true;
			}
		}
	}

	return -1;
}
저작자표시 (새창열림)

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

백준 10867번 중복 빼고 정렬하기 // C++  (0) 2020.04.22
백준 1406번 에디터 // C++  (0) 2020.04.22
백준 5427번 불 // C++  (0) 2020.03.18
백준 6593번 상범 빌딩 // C++  (0) 2020.03.18
백준 8972번 미친 아두이노 // C++  (0) 2020.03.18
    'Old/백준' 카테고리의 다른 글
    • 백준 10867번 중복 빼고 정렬하기 // C++
    • 백준 1406번 에디터 // C++
    • 백준 5427번 불 // C++
    • 백준 6593번 상범 빌딩 // C++
    mang_dev
    mang_dev

    티스토리툴바