题目描述
本题就类似于小游戏拼图,将九宫格中扣去一块,可以导致拼图可以移动,现在问你,给定一个图形,是否可以通过移动得到另一种形状。如果可以,输出最小步数,否则输出-1。
解题思路
首先我们可以看出,移动的方向,只能是上下左右四个方向移动,并且只可以将有数字(‘1’ ~ ‘8’)的位置移向空格(‘.’)的位置。反过来可以看出,只有’.’可以上下左右四个方向移动。
我们可以把九宫格3*3的图一维来表示。这里如果基础好的就可以直接跳过了。
如图我们可以把
3*3
的空间压成1*9
的空间,这时候我们在三维空间中上下左右的移动,就可以在一维空间中,将下标值 -3,+3,-1,+1来表示。
比如:1图空格
移动到6
的位置,就可以在2图中将空格
向左移动3格即下标-3 就到了6
的位置
所以我们就可以把一个三维图形用一个字符串表示,即一个字符串就可以表示一个九宫格的状态。
首先我的思路:步数最小,优先考虑广搜,我们把开始的状态通过题目中所规定的移动规则,不断一层一层的搜索,如果在搜索的过程中找到了终止的状态,那就直接输出步数,注意边搜索边标记,通过map<string,int>
来对字符串进行标记和查询是否标记。
但是很不幸,TEL超时了,只过了60%的数据。
考虑双广搜的思想,起点和终点一起搜索,定义两个map映射:M1、M2,分别表示起点状态到当前状态的步数和终点状态到当前状态的步数,一起搜索的过程中,如果发现一个状态在M1和M2中都不为0,则把其对接一起。然后就A~啦,啊哈哈!
代码部分
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <queue>
#include <map>
using namespace std;
map <string, int> M1;
map <string, int> M2;
typedef pair <string, int> P;
int dir[4] = {1, -1, 3, -3};
string s, e; // s 代表起始, e 代表结束
bool judge(int x)
{
if(x < 0 || x > 8)
return false;
else
return true;
}
int bfs()
{
P pre1, nex1, pre2, nex2;
pre1.first = s;
pre1.second = 0;
pre2.first = e;
pre2.second = 0;
queue <P> Q1;
queue <P> Q2;
M1[s] = 0;
M2[s] = 0;
Q1.push(pre1);
Q2.push(pre2);
while(!Q1.empty())
{
pre1 = Q1.front();
Q1.pop();
pre2 = Q2.front();
Q2.pop();
string ts1 = pre1.first;
int tn1 = pre1.second;
string ts2 = pre2.first;
int tn2 = pre2.second;
int it1 = ts1.find('.');
int it2 = ts2.find('.');
if(ts1 == e)
{
return tn1;
}
for(int i = 0; i < 4; ++ i)
{
int t1 = it2 + dir[i];
string t2 = ts2;
char t3 = t2[it2];
t2[it2] = t2[t1];
t2[t1] = t3;
int t4 = tn2 + 1;
if((i == 0 && (it2 == 2 || it2 == 5))||(i == 1 && (it2 == 3 || it2 == 6)))
continue;
if(judge(t1))
{
if(M2[t2])
continue;
M2[t2] = tn2 + 1;
if(M1[t2])
return M1[t2] + M2[t2];
nex2.first = t2;
nex2.second = t4;
Q2.push(nex2);
}
}
for(int i = 0; i < 4; ++ i)
{
int t1 = it1 + dir[i];
string t2 = ts1;
char t3 = t2[it1];
t2[it1] = t2[t1];
t2[t1] = t3;
int t4 = tn1 + 1;
if((i == 0 && (it1 == 2 || it1 == 5))||(i == 1 && (it1 == 3 || it1 == 6)))
continue;
if(judge(t1))
{
if(M1[t2])
continue;
M1[t2] = tn1 + 1;
if(M2[t2])
return M1[t2] + M2[t2];
nex1.first = t2;
nex1.second = t4;
Q1.push(nex1);
}
}
}
return -1;
}
int main()
{
int ans;
cin >> s >> e;
ans = bfs();
if(ans == -1)
cout << "-1" << endl;
else
cout << ans << endl;
return 0;
}