Compy's Blog
770 words
4 minutes
[BOJ] Shooting Game
2025-03-31

Shooting Game

TimeLimitMemoryLimitConditionTAG
1s512MB(5 ≤ N ≤ 100, 1 ≤ K ≤ 15)Dynamic Programming

처음에는 그냥 간단히 bfs로 풀이할 수 있을거라고 생각했다..

그래서

#include <iostream>
#include <vector>
#include <queue>
#include <tuple>

#define inf 1000000000
using namespace std;
using ll = long long;

int n, m;

pair<int, int> bomb[16];

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;
    
    for(int i = 0; i < m; i++) cin >> bomb[i].first >> bomb[i].second;
    
    int cp;
    cin >> cp;
    
    priority_queue<pair<int, pair<int, short>>, vector<pair<int, pair<int, short>>>, greater<pair<int, pair<int, short>>>> q; // {current_time, {current_position, current_visited}}
    
    q.push({0, {cp, 0}});
    
    short complete = 1;
    for(int i = 0; i < m; i++) complete |= 1 << i;
    
    
    
    while(!q.empty()){
        auto [time, _] = q.top(); q.pop();
        auto [pos, visited] = _;
        
//        cout << "time: " << time << "\npos: " << pos << ", " << visited << "\n";
        
        if(visited == complete) {
            cout << time;
            return 0;
        }
        
        bool impossible = false;
        for(int i = 0; i < m; i++){
            if(visited & (1 << i)) continue;
//            cout << "time: " << bomb[i].first + time + 1 << "\npos: " << i << ", " << n << "\n";

            if(abs(pos - bomb[i].second) + time + 1 >= n || bomb[i].first + time >= n){
                impossible = true;
                break;
            }
            
        }
        
        if(impossible) continue;
        
        for(int i = 0; i < m; i++){
            if(visited & (1 << i)) continue;
            q.push({time + abs(pos - bomb[i].second) + 1, {bomb[i].second, visited | (1 << i)}});
        }
        
        
    }
    
    cout << -1;
    
    
    
    return 0;
    
    
    
}

역시.. 당연히 시간초과가 나왔다.. 이때 든 생각… “dp냐 너?”

보통 이런 어이없는 결과를 보게된다면 의심해보게 된다.

아 근데 결국 dp로 접근을 못하고 그냥 bfs를 잘 최적화해보기로 맘을 먹고서 각 위치, 시간, 그리고 방문한 상태를 가지고 중복 실행이 되지 않도록 만들고, 이거를 토대로 돌렸다.

이 과정에서 bitset이라는 썼는데 또 xcode는 include 안해도 알아서 처리를 해줘서 boj에서 많이 틀리는 원인이 되었다.. 허허…

결국 최종적으로는 그냥 visited처리를 좀 더 잘한 코드로 ac를 받았다…

정답 코드
#include <iostream>
#include <vector>
#include <queue>
#include <tuple>
#include <bitset>

#define inf 1000000000
using namespace std;
using ll = long long;

int n, m;

pair<int, int> bomb[16];
bitset<(1<<15)> dp[101][101];


void print(int current){
    cout << "state: ";
    while(current > 0){
        cout << (current & 1) << " ";
        current/=2;
    }
    cout << "\n";
}

int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    cin >> n >> m;
    
    for(int i = 0; i < m; i++) cin >> bomb[i].first >> bomb[i].second;
    
    int cp;
    cin >> cp;
    
    
    priority_queue<pair<int, pair<int, short>>, vector<pair<int, pair<int, short>>>, greater<pair<int, pair<int, short>>>> q; // {current_time, {current_position, current_visited}}
    
    q.push({0, {cp, 0}});
    
    short complete = 1;
    for(int i = 0; i < m; i++) complete |= 1 << i;
    
    
    
    while(!q.empty()){
        auto [time, _] = q.top(); q.pop();
        auto [pos, visited] = _;
        
//        cout << "time: " << time << "\npos: " << pos << ", " << visited << "\n";
//        cout << "time: " << time << "\n";
//        print(visited);
        
        if(visited == complete) {
            cout << time;
            return 0;
        }
        
        bool impossible = false;
        for(int i = 0; i < m; i++){
            if(visited & (1 << i)) continue;
            if(abs(pos - bomb[i].second) + time + 1 >= n || bomb[i].first + time + abs(pos - bomb[i].second) >= n){
                impossible = true;
                break;
            }
        }
        
        if(impossible) continue;
        
        for(int i = 0; i < m; i++){
            if(visited & (1 << i)) continue;
            if(dp[time + abs(pos - bomb[i].second) + 1][bomb[i].second][visited | (1 << i)]) continue;
            q.push({time + abs(pos - bomb[i].second) + 1, {bomb[i].second, visited | (1 << i)}});
            dp[time + abs(pos - bomb[i].second) + 1][bomb[i].second][visited | (1 << i)] = true;
        }
        
        
    }
    
    cout << -1;
    

    
    
    
    
    
    
    return 0;
    
    
    
}


/*
 
 3 1
 2 1
 2

 5 3
 1 2
 1 4
 1 5
 3

 
 4 3
 3 1
 2 1
 1 1
 1
 
 
 1 1
 1 1
 1
 
 
 
 3 2
 1 1
 1 2
 
 
 
 100 1
 96 1
 5
 */
[BOJ] Shooting Game
https://compy07.github.io/Blog/posts/boj/25607/
Author
뒹굴뒹굴 이정훈 공부방
Published at
2025-03-31