Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge
魔板由8个大小相同方块组成,分别用涂上不同颜色,用1到8的数字表示。
其初始状态是
1 2 3 4
8 7 6 5
对魔板可进行三种基本操作:
A操作(上下行互换):
8 7 6 5
1 2 3 4
B操作(每次以行循环右移一个):
4 1 2 3
5 8 7 6
C操作(中间四小块顺时针转一格):
1 7 2 4
8 6 3 5
用上述三种基本操作,可将任一种状态装换成另一种状态。输入包括多个要求解的魔板,每个魔板用三行描述。
第一行步数N(不超过10的整数),表示最多容许的步数。
第二、第三行表示目标状态,按照魔板的形状,颜色用1到8的表示。
当N等于-1的时候,表示输入结束。对于每一个要求解的魔板,输出一行。
首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是A、B或C),相邻两个操作之间没有任何空格。
注意:如果不能达到,则M输出-1即可。
45 8 7 64 1 2 338 7 6 51 2 3 4-1
2 AB1 A
题目分析
求由初始状态变为给定状态需要几步
注意到初始状态为
1234
8765
题目输入的是结束状态,同时其要求解法是在给定步数内,
所以当入队列的状态的步数超过了,可以提前结束搜索,
#include <cstdio> #include <vector> #include <queue> #include <iostream> #include <algorithm> std::vector<std::string> visited; bool unvisited(std::string data) { std::vector<std::string>::iterator res = find(visited.begin(), visited.end(), data); return res == visited.end(); } std::string change(std::string init, char c) { std::string str = ""; if (c == 'A') str = str + init[4] + init[5] + init[6] + init[7] + init[0] + init[1] + init[2] + init[3]; else if (c == 'B') str = str + init[3] + init[0] + init[1] + init[2] + init[7] + init[4] + init[5] + init[6]; else str = str + init[0] + init[5] + init[1] + init[3] + init[4] + init[6] + init[2] + init[7]; return str; } int main() { int steps; std::string init = "12348765"; char c; while (scanf("%d", &steps)) { if (steps == -1) break; int ans; std::string target = ""; for (int i = 0; i < 8; ++i) { scanf("%d", &ans); c = '1' + ans - 1; target = target + c; } if (init == target) { if (0 >= steps) printf("0\n"); else printf("-1\n"); continue; } if (!visited.empty()) visited.clear(); std::queue<std::string> q; std::queue<std::string> path; q.push(init); path.push(""); visited.push_back(init); std::string sol = ""; bool flag = true; while (!q.empty() && flag) { std::string state = q.front(); q.pop(); std::string nowpath = path.front(); path.pop(); std::string newstate; std::string newpath; for (int i = 0; i < 3; ++i) { c = 'A' + i; newstate = change(state, c); newpath = nowpath + (c); if (newpath.length() > steps) { flag = false; break; } if (newstate == target) { sol = newpath; flag = false; break; } if (unvisited(newstate)) { //std::cout << newstate << std::endl; q.push(newstate); path.push(newpath); visited.push_back(newstate); } } } if (sol.length() <= steps && !flag) std::cout << sol.length() << " " << sol << std::endl; else printf("-1\n"); } }