Created
October 28, 2021 16:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include<iostream> | |
#include<queue> | |
#include<cstring> | |
using namespace std; | |
// index번째 디스크가 몇번째 기둥에 있는지 | |
int get(int state, int index) { | |
return (state >> (index * 2)) & 3; | |
} | |
// index번째 디스크를 value번째 기둥으로 옮기기 | |
int set(int state, int index, int value) { | |
return (state & ~(3 << (index * 2))) | (value << (index * 2)); | |
} | |
// x 부호 반환 | |
int sgn(int x) { if (!x)return 0; return x > 0 ? 1 : -1; } | |
// x의 절대값 1증가 | |
int incr(int x) { if (x < 0) return x - 1; return x + 1; } | |
int c[1 << (12 * 2)]; | |
// discs개의 디스크가 begin상태에서 end상태로 가기위한 최소 움직임 수 | |
int bidir(int discs, int begin, int end) { | |
if (begin == end)return 0; | |
queue<int> q; | |
memset(c, 0, sizeof(c)); | |
// 정방향 탐색은 양수, 역방향 탐색은 음수로 양방향 탐색 | |
q.push(begin); c[begin] = 1; | |
q.push(end); c[end] = -1; | |
while (!q.empty()) { | |
int here = q.front(); | |
q.pop(); | |
int top[4] = { -1,-1,-1,-1 }; | |
// 각 기둥에 제일 위에 있는 disc계산 | |
for (int i = discs - 1; i >= 0; i--) | |
top[get(here, i)] = i; | |
// i번째 기둥 맨 위에 있는 disc를 j번째 기둥으로 옮기기 | |
for (int i = 0; i < 4; i++) | |
if(top[i]!=-1) | |
for(int j=0; j<4; j++) | |
// j번째 기둥은 비어 있거나, 맨 위의 disc가 제일 거야함 | |
if (i != j && (top[j] == -1 || top[j] > top[i])) { | |
int there = set(here, top[i], j); | |
if (c[there] == 0) { | |
c[there] = incr(c[here]); | |
q.push(there); | |
} | |
else if (sgn(c[there]) != sgn(c[here])) | |
return abs(c[there]) + abs(c[here]) - 1; | |
} | |
} | |
return -1; | |
} | |
int main() { | |
int testcase; | |
cin >> testcase; | |
while (testcase--) { | |
int n, begin = 0, end = 0; | |
cin >> n; | |
for (int i = 0; i < 4; i++) { | |
int num; | |
cin >> num; | |
for (int j = 0; j < num; j++) { | |
int discNum; | |
cin >> discNum; | |
begin |= i << ((discNum - 1) * 2); | |
} | |
} | |
for (int i = 0; i < n; i++) { | |
end |= 3 << (i * 2); | |
} | |
cout << bidir(n, begin, end) << endl; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment