题意:俩个转盘,24个数字,每个转盘都可以顺时针,逆时针旋转.终点固定.
问:给定一个起点,能不能在16步内转到终点
解法:双向bfs,终点走8步,起点走8步,判断从起点生成的状态是否在终点里面,如果在即是有解
注意题目要输出转动的方向,并且方向字符串要最小,所以,在某一步有解事,要把当前层数走完,取最小值
#include <iostream> #include<map> #include<memory.h> #include<stdio.h> #include<string> #include<queue> using namespace std; const int MAXN = 24; string zhuan(string str, int way) { string reStr(str); if (way == 1) { //左边顺时针旋转 char sb1 = str[10]; char sb2 = str[11]; for (int i = 11;i >= 2;i--) reStr[i] = reStr[i - 2]; reStr[1] = sb2; reStr[0] = sb1; reStr[23] = reStr[11]; reStr[22] = reStr[10]; reStr[21] = reStr[9]; } else if (way == 3) { //左边逆时针旋转 char sb1 = reStr[0]; char sb2 = reStr[1]; for (int i = 0;i < 10;i++) reStr[i] = reStr[i + 2]; reStr[11] = sb2; reStr[10] = sb1; reStr[23] = reStr[11]; reStr[22] = reStr[10]; reStr[21] = reStr[9]; } else if (way == 2) { //右边顺时针旋转 char sb1 = reStr[12]; char sb2 = reStr[13]; for (int i = 12;i < 22;i++) reStr[i] = reStr[i + 2]; reStr[23] = sb2; reStr[22] = sb1; reStr[11] = reStr[23]; reStr[10] = reStr[22]; reStr[9] = reStr[21]; } else { //右边逆时针旋转 char sb1 = reStr[22]; char sb2 = reStr[23]; for (int i = 23;i >= 12;i--) reStr[i] = reStr[i - 2]; reStr[13] = sb2; reStr[12] = sb1; reStr[11] = reStr[23]; reStr[10] = reStr[22]; reStr[9] = reStr[21]; } return reStr; } class Node { public: string str; string step; int stepNum; bool operator < (const Node& node) const { return stepNum > node.stepNum; } }; const static string endState = "034305650121078709a90121"; map<string, string> sMap; map<string, string>eMap; priority_queue<Node> q; int ok = 0; string curStep = ""; string path(string es) { string str = ""; for (int i = es.size() - 1; i >= 0;i--) { if (es.at(i) == '1') str+= "3"; else if (es.at(i) == '3') str += "1"; else if (es.at(i) == '2')str += "4"; else if (es.at(i) == '4') str += "2"; } return str; } //8 void bfsEnd() { while (!q.empty()) q.pop(); Node n; n.step = ""; n.stepNum = 0; n.str = endState; q.push(n); eMap[endState] = ""; while (!q.empty()) { n = q.top(); q.pop(); if (n.stepNum == 8) break; for (int i=1;i<=4;i++) { string str = zhuan(n.str, i); if (eMap.find(str) == eMap.end()) { string sstep(n.step); sstep += i + '0'; Node nn; nn.stepNum = n.stepNum + 1; nn.str = str; nn.step = sstep; q.push(nn); eMap[str] = sstep; } } } } void bfsStart(string str) { while (!q.empty()) q.pop(); Node n; n.step = ""; n.stepNum = 0; n.str = str; q.push(n); int okStep = INT32_MAX; while (!q.empty()) { n = q.top(); q.pop(); if (ok && n.stepNum != okStep) break; if (eMap.find(n.str) != eMap.end()) { if (ok == 0) { curStep = n.step+path(eMap.find(n.str)->second); okStep = n.stepNum; ok = 1; } else { string step = n.step + path(eMap.find(n.str)->second); //判断大小 if (strcmp(curStep.c_str(), step.c_str()) > 0) curStep = step; } } if (ok) continue; for (int i = 1; i <= 4 && n.stepNum != 8; i++) { str = zhuan(n.str,i); if (sMap.find(str) == sMap.end()) { string sstep(n.step); sstep += i + '0'; Node nn; nn.stepNum = n.stepNum + 1; nn.str = str; nn.step = sstep; sMap[str] = sstep; q.push(nn); } } } } int main() { int k = 0; cin >> k; eMap.clear(); bfsEnd(); while (k--) { ok = 0; sMap.clear(); string str = ""; int j; for (int i = 0;i < MAXN;++i) { cin >> j; if (j == 10) str += 'a'; else str += j + '0'; } if (str == endState) { cout << "PUZZLE ALREADY SOLVED" << endl; continue; } bfsStart(str); if (ok==0) { cout << "NO SOLUTION WAS FOUND IN 16 STEPS" << endl; continue; } cout << curStep << endl; } }