Koder / 박성훈
article thumbnail

DP + BFS 문제.

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

 

16397번: 탈출

첫 번째 줄에 N (0 ≤ N ≤ 99,999), T (1 ≤ T ≤ 99,999), G (0 ≤ G ≤ 99,999)가 공백 하나를 사이에 두고 주어진다. 각각 N은 LED로 표현된 수, T는 버튼을 누를 수 있는 최대 횟수, G는 탈출을 위해 똑같이

www.acmicpc.net

 

dp[k] 를 숫자 $K$를 만드는데 필요한 최소한의 버튼 누름 횟수 라고 하고,

숫자 $K$인 상태에서 두 버튼을 눌렀을때 변화하는 수를 각각 $A(K)$, $B(K)$ 이라고 하면

 

dp[A(K)] = dp[k] + 1

dp[B(K)] = dp[k] + 1

이 된다.

 

버튼 A, B를 누를 때 각각 숫자가 99,999를 넘어가는 경우에 대한 처리가 필요함에 유의.

만들어진 dp는 B(K) 버튼을 눌렀을때 수가 작아질 수도 있다는 특성 때문에

상향식 방식으로 구현하기에 어려움이 좀 있고,

깔끔하게 BFS로 구현해서 풀었다.

 

그냥 방문처리만 하는 BFS로도 문제를 해결할 수 있을듯 싶은데,

나는 개인적으로는 방문처리용 배열을 만드느니 DP로 짜는걸 선호해서

DP로 풀어보았다.

#include <bits/stdc++.h>
#define MAX 998244353
using namespace std;

int dp[123456] = {0};
// dp[k] : 숫자 K를 만드는데 필요한 최소한의 버튼누름 횟수. 

int A(int k){
	if(k+1 > 99999) return -1;
	return k+1;
}

int B(int k){
	if(k == 0) return k;
	k *= 2;
	
	if(k > 99999) return -1;
	
	int tmp = 1;
	for(int i=k; i>=10; i/=10) tmp *= 10;
	return k-tmp;
}

void bfs(int k){
	for(int i=0; i<123456; i++) dp[i] = MAX;
	
	int a,b;
	queue<int> q;
	q.push(k);
	dp[k] = 0;

	while(!q.empty()){
		int now = q.front();
		q.pop();
		
		a = A(now);
		b = B(now);
		
		if(a != -1 && dp[a] == MAX){
			dp[a] = dp[now]+1;
			q.push(a);
		}
		if(b != -1 && dp[b] == MAX){
			dp[b] = dp[now]+1;
			q.push(b);
		}
	}
	return;
}

int main(){
	int N,T,G;
	cin >> N >> T >> G;
	
	bfs(N); // N -> G;
	int ans = dp[G];
	
	if(ans == MAX || ans > T) cout << "ANG";
	else cout << ans;
	return 0;
}

반응형