Machineboy空

12869 : 뮤탈리스크 - BFS, DP 본문

Computer/Coding Test

12869 : 뮤탈리스크 - BFS, DP

안녕도라 2024. 2. 27. 14:34

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

 

12869번: 뮤탈리스크

1, 3, 2 순서대로 공격을 하면, 남은 체력은 (12-9, 10-1, 4-3) = (3, 9, 1)이다. 2, 1, 3 순서대로 공격을 하면, 남은 체력은 (0, 0, 0)이다.

www.acmicpc.net

문제요약

hp가 0이 될 때까지 공격 최소 횟수

 

난이도

Gold 4


풀이 포인트

  • Struct 사용법
// 세 개 부터는 튜플인데, 귀찮으니 struct
struct A{
    int a,b,c;
};

queue<A>q;
  • 그래프로  치환하여 생각하기

  • 음수 막아주는 코드
int na = max(0, a - _a[i][0]);
int nb = max(0, b - _a[i][1]);
int nc = max(0, c - _a[i][2]);
  • 3차원 배열이든, 2차원 배열이든 결국 한 점에 도달하기 위한 지도


REVIEW

 

첫번째 생각했던 아이디어는,

남은 hp를 내림차순 정렬 후, 9,3,1 순으로 빼주는 것. 즉 큰 숫자 부터 큰 값을 빼주는 것이었다.

테스트 케이스 5개는 통과, 나머지 하나는 통과하지 않는 아이디어였다.

 

그리고서, 9,3,1을 순열로 나열해, 차례로 빼줘 보자고 생각하고

또 재귀함수로 뻗어나가는 꼴을 생각했는데 또 그 스케일에 무너져서 포기함.

 

모범 답안에서 배워야 할 것 첫 번째. struct 자료 구조의 사용.

늘상 내가 원하는 구조의 자료구조를 딱 알맞게 설정하는 것이 어려운데,

pair를 넘어서는 구조가 특히 고민이되는 순간이 많았다. 지피티에 물어보면 튜플의 사용법을 알려줬는데 이런 방법이!

 

struct를 선언하고 queue에 그 구조체를 담아 사용하는 방법.

 

두번째, 그래프로 치환해서 생각하기.

이 문제를 bfs로 치환해 생각한다는 것이 꽤나 충격이었다.

미연시나 선택에 따라 다른 결말에 도달하는 느낌의 경우의 수를 그래프 모양으로 상상할 수 있어야 한다.

이 문제의 경우에도 6가지 순열에 따라 나타나는 다른 결과값을 하나의 노드, 또 그 노드에서 6가지로 뻗어나가는 엣지로 이루어진

그래프로 치환하여 생각하는 것이 중요.

 

내가 계속해서 재귀를 떠올리는 것을 재귀 구현이 아닌 그래프 구현 후 탐색 방법 생각으로 이어지게끔 하면 될 것 같다.

 

그래프로 바꿔 생각한 후에는 최단거리 bfs문제가 되어버린다.

 

참 또 간단한 수학 문제인듯한데 코드 구현이 어려워 막막했다가 여러가지를 배웠다.

 


CODE

 

#include <bits/stdc++.h> 
using namespace std;
const int INF = 987654321;
int dp[64][64][64], a[3], n, visited[64][64][64]; 
int _a[6][3] = {
	{9, 3, 1}, 
	{9, 1, 3}, 
	{3, 1, 9}, 
	{3, 9, 1}, 
	{1, 3, 9}, 
	{1, 9, 3}
};
struct A{
    int a, b, c; 
}; 
queue<A>q; 
int solve(int a, int b, int c){
    visited[a][b][c] = 1; 
    q.push({a, b, c}); 
    while(q.size()){
        int a = q.front().a; 
        int b = q.front().b; 
        int c = q.front().c; 
        q.pop();
        if(visited[0][0][0]) break;
        for(int i = 0; i < 6; i++){
            int na = max(0, a - _a[i][0]);
            int nb = max(0, b - _a[i][1]); 
            int nc = max(0, c - _a[i][2]); 
            if(visited[na][nb][nc]) continue;
            visited[na][nb][nc] = visited[a][b][c] + 1;  
            q.push({na, nb, nc}); 
        }
    }
    return visited[0][0][0] - 1;   
}
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
	cin >> n; 
	for(int i = 0; i < n; i++) cin >> a[i]; 
	cout << solve(a[0], a[1], a[2]) << "\n"; 
    return 0;
}

'Computer > Coding Test' 카테고리의 다른 글

12851 : 숨바꼭질 2 - BFS  (1) 2024.02.29
15537 : 괄호 추가하기 - 재귀  (1) 2024.02.28
4179 : 불! - BFS  (1) 2024.02.27
16235: 인구 이동 - DFS  (0) 2024.02.23
2589 : 보물섬 - BFS  (0) 2024.02.22