题目描述
你玩过华容道的游戏吗?这是个类似的,但更简单的游戏。看下面 3 x 2 的格子
+---+---+---+
| A | * | * |
+---+---+---+
| B | | * |
+---+---+---+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入
输入存在多组测试数据,对于每组测试数据:
输入两行6个字符表示当前的局面
输出
对于每组测试数据输出一个整数表示答案
样例输入
* A
**B
A B
***
样例输出
17
12
思路
这是一道你一眼看不出他想让你干啥的题目,是让你求最短路径呢,还是让你求能交换位置的方案数,经过多次实践,事实告诉我这是在求最短路径=_=
做题思路:
1、利用gets()读取带有空格的字符串
2、每个星号*都是不一样的,要区分,不然答案会不对
3、利用字符串存储每个状态,某个字符位置是i,上下左右就是i-3, i+3, i-1,i+1,特定位置要特殊判断
4、利用vis记录是否遍历过某状态,避免重复进入死循环
5、最短路径就是bfs,具体见代码,有注释
代码
#include<bits/stdc++.h>
using namespace std;
//判断A和B是否已经交换位置
bool check(string &s, int a, int b){
int flag = 0;
for(int i=0; i<s.size(); i++){
if(s[i]=='A' && i==b)
flag++;
if(s[i]=='B' && i==a)
flag++;
}
return flag==2;
}
int main(){
char s[2][3];
while(gets(s[0])){
//记录路径是否已经被走过
map<string, int> vis;
//记录最小步数
int ans = 0;
gets(s[1]);
string a;
//cnt记录*号,每个*号都不一样
int apos, bpos, cnt = 0;
//将输入转化为一个字符串,空格' '和'A' 'b'不变,将*转化为0 1 2 3...
for(int i=0; i<2; i++){
for(int j=0; j<3; j++){
if(s[i][j]=='*'){
a += cnt + '0';
cnt++;
}
else
a += s[i][j];
if(s[i][j]=='A')
apos = i*3+j;
if(s[i][j]=='B')
bpos = i*3 + j;
}
}
//标志初始状态已遍历过
vis[a] = 1;
queue<string> que;
que.push(a);
int flag = 0;
while(que.size()){
int n = que.size();
while(n--){
string t = que.front();
que.pop();
int pos;
flag = 0;
for(int i=0; i<6; i++){
if(t[i]==' '){
pos = i;
break;
}
}
//上
if(pos-3>=0){
string tmp = t;
swap(tmp[pos], tmp[pos-3]);
if(check(tmp, apos, bpos)){
flag = 1;
break;
}else if(!vis[tmp]){
que.push(tmp);
vis[tmp] = 1;
}
}
//下
if(pos+3<6){
string tmp = t;
swap(tmp[pos], tmp[pos+3]);
if(check(tmp, apos, bpos)){
flag = 1;
break;
}else if(!vis[tmp]){
que.push(tmp);
vis[tmp] = 1;
}
}
//左
if(pos-1>=0 && pos!=3){
string tmp = t;
swap(tmp[pos], tmp[pos-1]);
if(check(tmp, apos, bpos)){
flag = 1;
break;
}else if(!vis[tmp]){
que.push(tmp);
vis[tmp] = 1;
}
}
//右
if(pos+1<6 && pos!=2){
string tmp = t;
swap(tmp[pos], tmp[pos+1]);
if(check(tmp, apos, bpos)){
flag = 1;
break;
}else if(!vis[tmp]){
que.push(tmp);
vis[tmp] = 1;
}
}
}
ans++;
if(flag)
break;
}
cout<<ans<<endl;
}
return 0;
}