๋นํธ๋ง์คํฌ(BitMask)
์งํฉ ์์๋ค์ ๊ตฌ์ฑ ์ฌ๋ถ๋ฅผ ํํํ ๋ ์ ์ฉํ ํ ํฌ๋์ด๋ค.
๊ธฐ๋ณธ ์๋ฆฌ
{1, 2, 3, 4, 5}๋ผ๋ ์งํฉ์ด ์๊ณ ์ด ์งํฉ์ ๋ถ๋ถ์งํฉ์ ๊ตฌํด์ผ ํ๋ค.
{1}, {2}, ..., {1, 2}, ..., {1, 2, 5}, ..., {1, 2, 3, 4, 5}
๋ฌผ๋ก ๊ฐ๋จํ ๋ฐ๋ณต๋ฌธ์ ํตํด ๊ฒฝ์ฐ์ ์๋ฅผ ๊ตฌํ ์ ์๋ค.
ํ์ง๋ง ๋นํธ ๋ง์คํน์ ํ๋ฉด ๊ฐ ์์๋ฅผ ์ธ๋ฑ์ค์ฒ๋ผ ํํํ์ฌ ํจ์จ์ ์ธ ์ ๊ทผ์ด ๊ฐ๋ฅํ๋ค.
{1, 2, 3, 4, 5} → 11111
{2, 3, 4, 5} → 11110
{1, 2, 5} → 10011
{2} → 00010
1) ์ฝ์
i๋ฒ ์งธ ๋นํธ ๊ฐ์ 1๋ก ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ค. ์ด๋ OR ์ฐ์ฐ์ ํ์ฉํ๋ค.
i = 3์ผ ๋, 10101 | (1 << 3) → 10101 | 01000 → 11101
2) ์ญ์
i๋ฒ ์งธ ๋นํธ ๊ฐ์ 0์ผ๋ก ๋ณ๊ฒฝํ๋ ค๊ณ ํ๋ค. ์ด๋ AND ์ฐ์ฐ๊ณผ NOT ์ฐ์ฐ์ ํ์ฉํ๋ค.
i = 3์ผ ๋, 11101 & (~1 << 3) → 11101 & 10111 → 10101
3) ์กฐํ
i๋ฒ์งธ ๋นํธ๊ฐ ๋ฌด์จ ๊ฐ์ธ์ง ์๋ ค๋ฉด AND ์ฐ์ฐ์ ํ์ฉํ๋ค.
10101 & (1 << i) → 0์ด๋ฉด i๋ฒ์งธ ๋นํธ ๊ฐ์ด 0์ด๋ค.
๋ฌธ์
https://www.acmicpc.net/problem/2098
#include <iostream>
#include <algorithm>
using namespace std;
const int INF = 1e9;
int N;
int W[16][16];
int dp[16][1 << 16];
int DFS(int cur, int visited)
{
int& ret = dp[cur][visited];
if (ret > 0)
return ret;
if (visited == (1 << N) - 1) { // ๋ชจ๋ ๋์๋ฅผ ๋ค ๋ฐฉ๋ฌธํจ
// ์ํ: ๋ค์ 0๋ฒ์งธ ๋์๋ก ๋์๊ฐ๋ค.
if (W[cur][0] != 0)
return W[cur][0];
return INF;
}
ret = INF;
for (int i = 0; i < N; i++)
if (W[cur][i] && !(visited & (1 << i)))
ret = min(ret, W[cur][i] + DFS(i, visited | (1 << i)));
return ret;
}
int main()
{
cin >> N;
for (int y = 0; y < N; y++)
for (int x = 0; x < N; x++)
cin >> W[y][x];
cout << DFS(0, 1);
return 0;
}
https://www.acmicpc.net/problem/1194
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int N, M;
char map[50][50];
bool visited[50][50][1 << 6];
int dir[4][2]{ {0,-1},{0,1},{-1,0},{1,0} };
typedef struct {
int x, y, cnt, key;
}Point;
int bfs(Point start)
{
queue<Point> q;
q.push(start);
visited[start.x][start.y][start.key] = true;
while (!q.empty()) {
Point cur = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = cur.x + dir[i][0], ny = cur.y + dir[i][1];
if (nx < 0 || nx >= N || ny < 0 || ny >= M || map[nx][ny] == '#' || visited[nx][ny][cur.key])
continue;
if (map[nx][ny] == '1') // ์ถ๊ตฌ
return cur.cnt + 1;
else if (map[nx][ny] == '.') {
q.push({ nx, ny, cur.cnt + 1, cur.key });
visited[nx][ny][cur.key] = true;
}
else if ('a' <= map[nx][ny] && map[nx][ny] <= 'f') { // ์ด์
int key = 1 << (map[nx][ny] - 'a');
q.push({ nx, ny, cur.cnt + 1, cur.key | key });
visited[nx][ny][cur.key | key] = true;
}
else if ('A' <= map[nx][ny] && map[nx][ny] <= 'F') { // ๋ฌธ
int door = 1 << (map[nx][ny] - 'A');
if (cur.key & door)
{
q.push({ nx, ny, cur.cnt + 1, cur.key });
visited[nx][ny][cur.key] = true;
}
}
}
}
return -1;
}
int main() {
cin.tie(NULL);
cout.tie(NULL);
ios::sync_with_stdio(false);
cin >> N >> M;
Point start{};
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> map[i][j];
if (map[i][j] == '0') {
start = { i, j, 0, 0 };
map[i][j] = '.';
}
}
}
cout << bfs(start);
}
https://www.acmicpc.net/problem/1102
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
int N, P;
int machine[16][16];
int dp[1 << 16];
int GetOnCount(int n)
{
if (n == 0)
return 0;
return GetOnCount(n >> 1) + (n & 1);
}
int GetMinCost(int state)
{
int& result = dp[state];
if (result != -1)
return result;
if (GetOnCount(state) >= P)
return 0;
result = 1e9;
for (int i = 0; i < N; i++)
if ((state & (1 << i))) { // ์๋ ์ค์ธ ๋ฐ์ ๊ธฐ(on)
for (int j = 0; j < N; j++) {
if ((state & (1 << j)) == 0) { // ๊ณ ์ฅ๋ ๋ฐ์ ๊ธฐ(off)
// on ๋ฐ์ ๊ธฐ๊ฐ off ๋ฐ์ ๊ธฐ ์๋
result = min(result, machine[i][j] + GetMinCost(state | (1 << j)));
}
}
}
return result;
}
int main()
{
string onoff;
cin >> N;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
cin >> machine[i][j];
cin >> onoff >> P;
int on = 0; // ํ์ฌ ์๋ ์ค์ธ ๋ฐ์ ๊ธฐ ๋๋ฒ ๋นํธ ์ ์ฅ
for (int i = 0; i < N; i++)
if (onoff[i] == 'Y')
on |= (1 << i); // i๋ฒ์งธ ๋นํธ์ 1(on) ์ฝ์
if (GetOnCount(on) >= P)
{
cout << 0;
return 0;
}
memset(dp, -1, sizeof(dp));
int result = GetMinCost(on);
if (result == 1e9)
cout << -1;
else
cout << result;
}
https://programmers.co.kr/learn/courses/30/lessons/92343
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAX_STATE 17
struct Point {
int index, state, ship, wolf;
};
vector<int> graph[MAX_STATE];
bool visited[MAX_STATE][1 << MAX_STATE];
int solution(vector<int> info, vector<vector<int>> edges)
{
int answer = 0;
for (auto edge : edges) {
graph[edge[0]].push_back(edge[1]);
graph[edge[1]].push_back(edge[0]);
}
queue<Point> q;
q.push({ 0,1,1,0 });
visited[0][1] = true;
while (!q.empty()) {
Point curr = q.front();
q.pop();
answer = max(answer, curr.ship);
for (int next : graph[curr.index]) {
int nstate = curr.state | (1 << next);
if (visited[next][nstate])
continue;
int ns = 0, nw = 0;
if (!(curr.state & (1 << next))) {
if (info[next]) { // ๋๋
if (curr.ship <= curr.wolf + 1)
continue;
nw = 1;
}
else { // ์
ns = 1;
}
}
visited[next][nstate] = true;
q.push({ next,nstate,curr.ship + ns,curr.wolf + nw });
}
}
return answer;
}