Algorithm/Baekjoon

[백준 1107 - c++] 리모컨

tjddneva 2022. 2. 6. 14:14

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

 

1107번: 리모컨

첫째 줄에 수빈이가 이동하려고 하는 채널 N (0 ≤ N ≤ 500,000)이 주어진다.  둘째 줄에는 고장난 버튼의 개수 M (0 ≤ M ≤ 10)이 주어진다. 고장난 버튼이 있는 경우에는 셋째 줄에는 고장난 버튼

www.acmicpc.net

 

매우 짜증나는 문제였다. 처음 든 생각은 쓸 수 있는 버튼으로 주어진 번호와 가장 가까운 숫자를 찾아내는 게 목표라고 생각했다. 그래서 주어진 번호를 자릿수를 어떻게 하다보면 될 줄 알았는데 결국 안되었다.

그래서 그 다음 생각해낸 방법이 그냥 주어진 번호부터 시작해서 1 씩 더하거나 빼면서 쓸 수 없는 버튼이 포함되어 있으면 넘어가고 누를 수 있는 번호면 멈춘 다음 그 번호를 입력하고 + 나 - 버튼을 누르는 횟수를 더하는 방식이다.

예를 들어 목표 채널이 5000번 이면 5001 5002 5003 으로 가면서 누를 수 있는 번호인가 확인하는 것이다. 물론 4999 4998 4997 쪽으로도 가면서 누를 수 있는 번호를 찾은 후 위로 갔을 때와 아래로 갔을 때 어떤 게 더 유리한지 비교 후 답을 고른다. 

결과적으로 성공하긴 했는데 처리해줘야 할 예외 사항이 엄청 많았다. 밑에 코드를 보면 알겠지만 처리해줘야 하는 예외사항을 적어보면

1. 목표 채널이 100 이면 시작을 100에서 하므로 못 누르는 번호가 있든 없든 0 을 출력해야 한다.

2. 만약 0~9 모든 번호를 누를 수 없으면 오로지 + - 를 눌러야 하는 횟수로 답을 정한다. 

3.  고장난 버튼이 없으면 번호를 눌러서 목표 채널로 이동하는 것과 + - 만 눌러서 목표 채널로 이동하는 것 중 더 적은 횟수를 답으로 고른다.

------ 여기까지는 위 아래로 숫자를 탐색해 나가기전에 미리 처리해서 답을 내주고 4번은 누를 수 있는 숫자를 탐색한 후에 

4. (주어진 번호보다 작은 누를 수 있는 번호 + +를 누르는 횟수) , (주어진 번호보다 큰 누를 수 있는 번호 + -를 누르는 횟수) , 그리고 (+ - 만 누르는 횟수) 3개를 비교해서 가장 작은 걸 찾아야 한다.

 

못 누르는 번호는 vector 를 하나 만들어서 거기에 저장하였고 주어진 번호를 일부러 string 으로 받아 find 함수로 못누르는 번호가 있는지 없는지 편리하게 찾았다. 

 

전체 코드이다.

#include <iostream>
#include <cstring>
#include <string.h>
#include <string>
#include <cmath>
#include <vector>
#include <numbers>
#include <math.h>
#include <algorithm>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <tuple>
#include <utility>
#include <typeinfo>
#include <iomanip>
#include <set>
#include <map>

using namespace std;

vector<char> v;

int main(void) {

	ios::sync_with_stdio(0);
	cin.tie(0);

	string n;
	int m;
	char k;
	cin >> n >> m;

	for (int i = 0; i < m; i++) {
		cin >> k;
		v.push_back(k);
	}

	if (n == "100") {
		cout << 0;
		return 0;
	}

	if (v.size() == 10) {
		cout << abs(100 - stoi(n));
		return 0;
	}
	
	if (m == 0) {
		if (n.length() < abs(stoi(n) - 100)) {
			cout << n.length();
		}
		else
			cout << abs(stoi(n) - 100);

		return 0;
	}

	string temp = n;
	int num = stoi(n);
	int flag = 0;
	int z = 0;
	while (z <= abs(stoi(n) - 100)) {
		for (auto c : v) {
			if (temp.find(c) != string::npos) {
				flag = 1;
				break;
			}
		}
		if (flag == 1) {
			num++;
			temp = to_string(num);
			flag = 0;
		}
		else {
			break;
		}
		z++;
	}
	
	string temp2 = n;
	int num2 = stoi(n);
	flag = 0;
	while (1) {
		for (auto c : v) {
			if (temp2.find(c) != string::npos) {
				flag = 1;
				break;
			}
		}
		if (flag == 1) {
			num2--;
			temp2 = to_string(num2);
			flag = 0;
		}
		else {
			break;
		}
	}
	
	int answer = min(num - stoi(n) + temp.length(), stoi(n) - num2 + temp2.length());

	if (answer < abs(stoi(n) - 100))
		cout << answer;
	else
		cout << abs(stoi(n) - 100);
}

'Algorithm > Baekjoon' 카테고리의 다른 글

[백준 12904 - c++] A와 B  (0) 2022.03.30
[백준 11049 - Java] 행렬 곱셈 순서  (0) 2022.02.24
[백준 11048 - Java] 이동하기  (1) 2022.02.22
[백준 23599 - C++] 밥  (0) 2022.02.16
[백준 12107 - c++] 약수 지우기 게임 1  (1) 2022.02.06