题目的意思就是能不能把输入的这种状态,通过16步变成指定状态,如果已经是最终状态,就输出已经完成,超过16步,就输出超过16步,不然就输出步骤。
我们可以做的操作是左边轮盘顺时针,逆时针,右边轮盘顺时针,逆时针四种。
输入前12个是左边轮盘,后12个是右边轮盘,注意左边最后三个,就是右边最后三个。
刚开始纯粹用bfs()结果超时了。一直在想要剪枝,可不知道剪什么,后来才知道原来是要用双向bfs()的。
先从最终状态往前八层,再从开始状态往后八层。
如果在前八层搜索过程中,搜到了后八层出现过的状态,说明可以转到,否则不能。
还有一点要注意,因为是用字符串存。所以10这个两位数是不能存的,我把10变成了a。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <queue>
using namespace std;
const int N = 30;
int t;
bool ok;
char tar[N];
char start[N] = "034305650121078709a90121";
struct state {
char s[30];
char step[30];
int stepnum;
}st,st1;
map<string,string>vis;
map<string,int>viss;
queue<state> q;
void change(int k){
if (k == 1) {
char temp1 = st1.s[10];
char temp2 = st1.s[11];
for (int i = 11; i >= 2; i --)
st1.s[i] = st1.s[i - 2];
st1.s[1] = temp2;
st1.s[0] = temp1;
st1.s[23] = st1.s[11];
st1.s[22] = st1.s[10];
st1.s[21] = st1.s[9];
}
if (k == 3) {
char temp1 = st1.s[0];
char temp2 = st1.s[1];
for (int i = 0; i < 10; i ++)
st1.s[i] = st1.s[i + 2];
st1.s[11] = temp2;
st1.s[10] = temp1;
st1.s[23] = st1.s[11];
st1.s[22] = st1.s[10];
st1.s[21] = st1.s[9];
}
if (k == 4) {
char temp1 = st1.s[22];
char temp2 = st1.s[23];
for (int i = 23; i >= 12; i --)
st1.s[i] = st1.s[i - 2];
st1.s[13] = temp2;
st1.s[12] = temp1;
st1.s[11] = st1.s[23];
st1.s[10] = st1.s[22];
st1.s[9] = st1.s[21];
}
if (k == 2) {
char temp1 = st1.s[12];
char temp2 = st1.s[13];
for (int i = 12; i < 22; i ++)
st1.s[i] = st1.s[i + 2];
st1.s[23] = temp2;
st1.s[22] = temp1;
st1.s[11] = st1.s[23];
st1.s[10] = st1.s[22];
st1.s[9] = st1.s[21];
}
}
void bfs(char *temp) {
vis.clear();
while (!q.empty())
q.pop();
strcpy(st.s,temp);
st.stepnum = 0;
st.step[0] = '\0';
vis[st.s] = "st";
q.push(st);
while (!q.empty()) {
st = q.front();
q.pop();
for (int i = 1; i <= 4; i++){
st1 = st;
change(i);
if (vis[st1.s] == "") {
st1.step[st1.stepnum++] = i + '0';
st1.step[st1.stepnum] = '\0';
vis[st1.s] = st1.step;
q.push(st1);
}
}
if (st.stepnum == 8)
return;
}
}
void bfs2(char *temp){
viss.clear();
while (!q.empty())
q.pop();
strcpy(st.s,temp);
st.stepnum = 0;
st.step[0] = '\0';
viss[st.s] = 1;
q.push(st);
while (!q.empty()){
st = q.front();
if (vis[st.s] != ""){
ok = true;
return;
}
q.pop();
for (int i = 1; i <=4; i++){
st1 = st;
change(i);
if (viss[st1.s] == 0){
st1.step[st1.stepnum++] = i + '0';
st1.step[st1.stepnum] = '\0';
viss[st1.s] = 1;
q.push(st1);
}
}
if (st.stepnum == 9)
return;
}
}
int main() {
scanf("%d",&t);
getchar();
while (t--) {
int temp;
ok = false;
for (int i = 0; i < 24; i++){
scanf("%d",&temp);
if (temp == 10)
tar[i] = 'a';
else
tar[i] = '0' + temp;
}
tar[24] = '\0';
if (strcmp(tar,start) == 0){
printf("PUZZLE ALREADY SOLVED\n");
continue;
}
bfs(start);
bfs2(tar);
if (ok){
printf("%s",st.step);
for (int i = vis[st.s].size() - 1; i >= 0; i--){
if (vis[st.s][i] == '1') printf("3");
if (vis[st.s][i] == '2') printf("4");
if (vis[st.s][i] == '3') printf("1");
if (vis[st.s][i] == '4') printf("2");
}
printf("\n");
}
else printf("NO SOLUTION WAS FOUND IN 16 STEPS\n");
}
return 0;
}