1150. 简单魔板
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB , Special Judge
Description
魔板由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
用上述三种基本操作,可将任一种状态装换成另一种状态。Input
输入包括多个要求解的魔板,每个魔板用三行描述。
第一行步数N(不超过10的整数),表示最多容许的步数。
第二、第三行表示目标状态,按照魔板的形状,颜色用1到8的表示。
当N等于-1的时候,表示输入结束。Output
对于每一个要求解的魔板,输出一行。
首先是一个整数M,表示你找到解答所需要的步数。接着若干个空格之后,从第一步开始按顺序给出M步操作(每一步是A、B或C),相邻两个操作之间没有任何空格。
注意:如果不能达到,则M输出-1即可。Sample Input
45 8 7 64 1 2 338 7 6 51 2 3 4-1
Sample Output
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");
}
}