
문제 분석 및 풀이
설계 분석
- 비트마스킹으로 같은 경로를 걸러내는 것이 중요한 문제
- 아래 과정을 P개 이상의 발전소가 켜질때 까지 반복
- 켜진 발전기중 하나 선택 (i)
- 꺼진 발전기중 하나 선택 (j)
- j 켜기
- i를 이용해서 j를 키는 비용을 추가
- 내 풀이는 P개 이상 켜졌을 때 전역변수에 최솟 값을 갱신하는 방법
- 더욱 최적화된 풀이는 각 상태의 최솟값을 배열에 저장해서 재사용
풀이
나의 풀이
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
using namespace std;
const int INF = 987654321;
int N, P;
int graph[16][16];
int minimum = INF;
unordered_map<int, int> umap;
void dfs(int mask, int val)
{
if (umap.find(mask) != umap.end())
{
int exsistingValue = umap[mask];
if (exsistingValue <= val) return;
}
umap[mask] = val;
int cnt = 0;
for (int i = 0; i < N; ++i) {
if ((mask >> i) & 1) {
cnt++;
}
}
if (cnt >= P)
{
minimum = min(minimum, val);
return;
}
for (int i=0; i<N; i++)
{
if (!(mask & (1 << i))) continue;
for (int j=0; j<N; j++)
{
if (mask & (1 << j)) continue;
dfs(mask | ( 1 << j ), val + graph[i][j]);
}
}
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> N;
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
int weight;
cin >> weight;
graph[i][j] = weight;
}
}
string onOffstat;
cin >> onOffstat;
int mask = 0;
for (int i=0; i<onOffstat.size(); i++)
{
if (onOffstat[i] == 'Y')
{
mask |= 1 << i;
}
}
cin >> P;
dfs(mask, 0);
minimum = minimum == INF ? -1 : minimum;
cout << minimum;
return 0;
}
개선 버전
#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <cstring>
using namespace std;
const int INF = 987654321;
int N, P;
int graph[16][16];
int minimum = INF;
int cost[1 << 16];
int dfs(int mask)
{
if (cost[mask] != -1)
{
return cost[mask];
}
int cnt = 0;
for (int i = 0; i < N; ++i)
{
if ((mask >> i) & 1)
cnt++;
}
if (cnt >= P)
{
return 0;
}
cost[mask] = INF;
for (int i=0; i<N; i++)
{
if (!(mask & (1 << i))) continue;
for (int j=0; j<N; j++)
{
if (mask & (1 << j)) continue;
cost[mask] = min(cost[mask], dfs(mask | ( 1 << j )) + graph[i][j]);
}
}
return cost[mask];
}
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(NULL);
memset(cost, -1, sizeof(cost));
cin >> N;
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
int weight;
cin >> weight;
graph[i][j] = weight;
}
}
string onOffstat;
cin >> onOffstat;
int mask = 0;
for (int i=0; i<onOffstat.size(); i++)
{
if (onOffstat[i] == 'Y')
{
mask |= 1 << i;
}
}
cin >> P;
minimum = dfs(mask);
if (minimum == INF)
{
minimum = -1;
}
cout << minimum;
return 0;
}