Description
题目和A题相同,在这里我们把数据范围扩大:N可能超过10。
请仔细考虑各种情况。
Input
输入包括多个要求解的魔板,每个魔板用三行描述。
第一行步数N,表示最多容许的步数。
第二、第三行表示目标状态,按照魔板的形状,颜色用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评分:M超过N或者给出的操作不正确均不能得分。
Problem Source: ZSUACM Team Member
#include <iostream>
#include <stdio.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
class MagicPad
{
public:
vector<char> changeHistory;
int magicPad[2][4];
MagicPad()
{
magicPad[0][0] = 1;
magicPad[0][1] = 2;
magicPad[0][2] = 3;
magicPad[0][3] = 4;
magicPad[1][0] = 8;
magicPad[1][1] = 7;
magicPad[1][2] = 6;
magicPad[1][3] = 5;
}
//上下行互换
void opA()
{
int temp[4];
for(int i = 0; i < 4; i++)
{
temp[i] = magicPad[0][i];
magicPad[0][i] = magicPad[1][i];
magicPad[1][i] = temp[i];
}
changeHistory.push_back('A');
}
//每次以行循环右移一个
void opB()
{
int temp[4];
int i;
for(i = 0; i < 4; i++)
temp[i] = magicPad[0][i];
for(i = 1; i < 4; i++)
magicPad[0][i] = temp[i-1];
magicPad[0][0] = temp[3];
for(i = 0; i < 4; i++)
temp[i] = magicPad[1][i];
for(i = 1; i < 4; i++)
magicPad[1][i] = temp[i-1];
magicPad[1][0] = temp[3];
changeHistory.push_back('B');
}
//中间四小块顺时针转一格
void opC()
{
int temp = magicPad[0][1];
magicPad[0][1] = magicPad[1][1];
magicPad[1][1] = magicPad[1][2];
magicPad[1][2] = magicPad[0][2];
magicPad[0][2] = temp;
changeHistory.push_back('C');
}
bool checkEqual(int finalState[][4])
{
for (int i = 0; i < 2; i++)
for (int j = 0; j < 4; j++)
if (magicPad[i][j] != finalState[i][j])
return false;
return true;
}
int getIndex()
{
return 10000 * (magicPad[0][0] * 1000 + magicPad[0][1] * 100 + magicPad[0][2] * 10 + magicPad[0][3]) + (magicPad[1][0] * 1000 + magicPad[1][1] * 100 + magicPad[1][2] * 10 + magicPad[1][3]);
}
};
int finalState[2][4];
int main()
{
int maxStep;
while(scanf("%d", &maxStep), maxStep!=-1)
{
for(int i = 0; i < 2; i++)
for(int j = 0; j < 4; j++)
scanf("%d", &finalState[i][j]);
queue<MagicPad> state;
state.push(MagicPad());
map<int, bool> isVisit;
bool succeed = false;
while(!state.empty())
{
MagicPad current = state.front();
if (current.changeHistory.size() > maxStep)
state.pop();
else if (current.checkEqual(finalState))
{
succeed = true;
printf("%d ", current.changeHistory.size());
for (int i = 0; i < current.changeHistory.size(); i++)
printf("%c", current.changeHistory[i]);
printf("\n");
break;
}
else
{
state.pop();
MagicPad next = current;
next.opA();
int index = next.getIndex();
if (!isVisit[index])
{
state.push(next);
isVisit[index] = true;
}
next = current;
next.opB();
index = next.getIndex();
if (!isVisit[index])
{
state.push(next);
isVisit[index] = true;
}
next = current;
next.opC();
index = next.getIndex();
if (!isVisit[index])
{
state.push(next);
isVisit[index] = true;
}
}
}
if (!succeed)
printf("-1\n");
}
return 0;
}
感想:
一开始直接BFS, 直接超时了。
后来加入是否visited过的判断,由于用的是数组保存isVIsited难以判断大小,开得太大超内存,太小runTImeError
最后用map<int, bool>代替数组顺利通过
所以,当难以判断数组大小的时候,尽量用map来代替