Problem Solving/BOJ

[백준 2001번] [BFS / 비트마스킹] 보석 줍기

  • -
728x90
반응형

그래프 탐색 관련한 문제라는 것은 문제를 읽자마자 쉽게 파악할 수 있다.

문제 상황에서 가장 크리티컬한 지점은 탐색과정에서 보석을 얼마나 가지고 있는지를 기억해야한다는 것이다. 왜냐하면, 보석을 얼마나 가지고 있는지에 따라서 방문할 수 있는 지역이 달라지기 때문이다.

 

따라서 BFS를 돌리는 과정에서, 보석을 얼마나 가지고 있는지를 기억하고 있으면 된다. 같은 지역에 있는 보석은 1번만 주울 수 있으므로, 비트마스킹을 통해 1개의 정수로 어느 지역의 보석을 가지고 있는지를 쉽게 저장해놓을 수 있다.

 

추가적으로 같은 지역을 방문하더라도 보석이 달라지면 경향성이 달라지므로, visited를 2차원 배열로 잡는다.

위 문제와 비슷한 느낌으로 이해해주면 된다. https://viyoung.tistory.com/360

 

[백준 1194번] [BFS / 비트마스킹] 달이 차오른다, 가자.

Approach 문제에서 이동 횟수의 최솟값을 묻는 상황이므로, BFS를 바로 떠올려주면 된다. 다만, 이 문제에서 되게 독특한 지점은 각 이동하는 상황에서 키를 가지고 있는지 여부가 굉장히 중요하다.

viyoung.tistory.com

#include <bits/stdc++.h> #define fastio ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0) using namespace std; typedef pair<int, int> pii; bool visited[101][1 << 14]; int main(void){ fastio; memset(visited, 0, sizeof(visited)); int n, m, k; cin >> n >> m >> k; map<int, int> s; for(int i = 0; i < k; i++){ int t; cin >> t; s[t] = i; } vector<vector<pii> > v(n + 1); for(int i = 0; i < m; i++){ int a, b, c; cin >> a >> b >> c; v[a].push_back(make_pair(b, c)); v[b].push_back(make_pair(a, c)); } queue<pii> q; q.push(make_pair(1, 0)); visited[1][0] = 1; int max_num = 0; while(!q.empty()){ int cur = q.front().first; int key = q.front().second; q.pop(); if(cur == 1){ if (s.find(cur) != s.end()){ max_num = max(max_num, __builtin_popcount(key | (1 << s[cur]))); } else max_num = max(max_num, __builtin_popcount(key)); } for (int i = 0; i < v[cur].size(); i++) { int to = v[cur][i].first; int limit = v[cur][i].second; if(s.find(cur) != s.end()){ if(__builtin_popcount(key | (1 << s[cur])) <= limit && !visited[to][key | (1 << s[cur])]){ q.push(make_pair(to, key | (1 << s[cur]))); visited[to][key | (1 << s[cur])] = 1; } } if (__builtin_popcount(key) <= limit && !visited[to][key]){ q.push(make_pair(to, key)); visited[to][key] = 1; } } } cout << max_num << "\n"; return 0; }
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.