https://www.acmicpc.net/problem/16992
16992번: 3-SAT
첫째 줄에 변수의 개수 N (1 ≤ N ≤ 100)과 절의 개수 M (1 ≤ M ≤ 1000)이 주어진다. 둘째 줄부터 M개의 줄에는 절이 주어진다. 절은 세 정수 i, j, k (1 ≤ |i|, |j|, |k| ≤ N)로 이루어져 있으며, i, j, k가
www.acmicpc.net
16992 3-SAT
알고리즘 : 휴리스틱(시뮬레이티드 어닐링)
시뮬레이티드 어닐링(담금질 기법)을 이용한 휴리스틱 풀이입니다. 휴리스틱이란 정해를 구하기엔 시간이 충분하지 않거나 정보의 부족으로 인하여 합리적인 해를 제시할 수 없을 때, 빠르게 사용할 수 있는 확률에 의지하는 방법 입니다.
SCPC에 자주 나오는 유형이라 이번에 새로 공부하게 되었는데, 정해가 정해진 문제보단 정해에 가까운 답을 유추해내는 실전에서 유용할 듯 합니다.
풀이에 이용되는 방법으론 가지치기, 시뮬레이티드 어닐링, 유전 알고리즘 등이 있으며 후에 관련 글을 작성하도록 하겠습니다.
현재 세대의 x들의 true / false 정보를 저장하는 b의 랜덤 인덱스에 토글을 하는 식으로 진행하여 중간에 답을 찾을 경우 탈출하는 식으로 진행하면 됩니다. 제한 시간에 최대한 맞춰 반복 횟수를 지정하는 편이 답을 얻어내는데 유리하므로 조정을 잘 하여야 합니다.
< CODE >
#include <iostream>
#include <random>
#include <vector>
#include <stdlib.h>
#include <ctime>
#include <cmath>
using namespace std;
int n,m;
int arr[3005];
int main() {
random_device rd;
mt19937 mt(rd());
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
uniform_int_distribution<int> ran(1, n);
for (int i = 0; i < m; i++)
{
int start = i * 3;
cin >> arr[start] >> arr[start+1] >> arr[start+2];
}
vector<bool> a(105, false), b(105, false);
int prv = 0;
double t = 1.0, k = 2.5;
for (int i = 0; i < 180001; i++)
{
b = a;
int rIdx = ran(mt);
b[rIdx] = !b[rIdx];
int now = 0;
for (int j = 0; j < m*3; j += 3)
{
bool chk = false;
chk |= ((arr[j] > 0) ? b[arr[j]] : !b[-arr[j]]);
chk |= ((arr[j + 1] > 0) ? b[arr[j + 1]] : !b[-arr[j + 1]]);
chk |= ((arr[j + 2] > 0) ? b[arr[j + 2]] : !b[-arr[j + 2]]);
if(chk)
now++;
}
double nowP = exp((double)(now - prv) / (k * t));
double rP;
if (n == 1)
rP = 0;
else
rP = ((double)ran(mt) - 1) / (n - 1);
if (nowP > rP)
{
a = b;
prv = now;
}
if (now == m)
{
cout << "1\n";
for (int j = 1; j <= n; j++)
cout << b[j] << ' ';
cout << '\n';
return 0;
}
t *= 0.9999;
}
cout << "0\n";
return 0;
}
시간 : 1740ms
태그 : #BOJ 3-SAT #백준 3-SAT #16992 3-SAT #3-SAT풀이 #시뮬레이티드어닐링 #담금질기법
'알고리즘' 카테고리의 다른 글
[백준] 400문제 달성! (PLATINUM IV) (0) | 2021.07.12 |
---|---|
[BOJ / DP] 13398 연속합 2 (0) | 2021.07.12 |
[BOJ / 플러드필 BFS] 2638 치즈 (0) | 2021.07.08 |
[BOJ / 메모이제이션 BFS] 2157 여행 (0) | 2021.07.06 |
[BOJ / 스택] 1918 후위 표기식 (0) | 2021.07.06 |