代码源自https://www.cnblogs.com/-Ackerman/p/12245117.html
可在http://oj.ecustacm.cn/problem.php?id=1296测试代码
题目描述
你玩过华容道的游戏吗?这是个类似的,但更简单的游戏。看下面 3 x 2 的格子
±–±--±–+
| A | * | * |
±–±--±–+
| B | | * |
±–±--±–+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入
输入存在多组测试数据,对于每组测试数据:
输入两行6个字符表示当前的局面
输出
对于每组测试数据输出一个整数表示答案
样例输入 Copy
* A
**B
A B
***
样例输出 Copy
17
12
- 求最少步数的华容道问题,使用bfs
- 同时避免走重复的情况
- 移动空白部分可以简化问题,而不用考虑同时移动A、B
#include <iostream>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <queue>
#include <math.h>
#include <cstdio>
#include <iomanip>
#include <time.h>
#define LL long long
#define INF 0x3f3f3f3f
#define ls nod<<1
#define rs (nod<<1)+1
const int maxn = 1e5 + 10 ;
const LL mod = 20010905;
char map[10][10];
int row_a,row_b,col_a,col_b,row,col;
// 两行分别代表x y的移动情况
int dir[4][2] = {0,1,0,-1,1,0,-1,0};
int vis[3][3][3][3][3][3];
struct Node {
int r,c;
int ar,ac;
int br,bc;
int step;
};
void bfs() {
std::queue<Node> q;
Node now;
// 把原坐标赋值给节点Node
now.r = row;
now.c = col;
now.ar = row_a,now.ac = col_a;
now.br = row_b,now.bc = col_b;
now.step = 0;
q.push(now);
while (!q.empty()) {
now = q.front();
q.pop();
// 剪枝条件,当已被访问了,执行下一层循环
if (vis[now.ar][now.ac][now.br][now.bc][now.r][now.c])
continue;
// 剪枝条件,当已被访问了,执行下一层循环
vis[now.ar][now.ac][now.br][now.bc][now.r][now.c] = 1;
// 出口条件
if (now.ar == row_b && now.ac == col_b && now.br == row_a && now.bc == col_a ) {
printf("%d\n",now.step);
return ;
}
// 分别执行四个方向的移动
for (int i = 0;i < 4;i++) {
// 移动的是空格的位置
int x = now.r + dir[i][0];
int y = now.c + dir[i][1];
if (x < 0 || x > 1 || y < 0 || y > 2)
continue;
// 新的空格位置的节点
Node ed = now;
ed.r = x,ed.c = y;
ed.step++;
if (x == now.ar && y == now.ac) {
ed.ac = now.c;
ed.ar = now.r;
}
// 调整A、B的坐标,把原空格位置赋值给新的A或B的位置
if (x == now.br && y == now.bc) {
ed.bc = now.c;
ed.br = now.r;
}
// 判重,是否重复出现同一种情况
if (vis[ed.ar][ed.ac][ed.br][ed.bc][ed.r][ed.c])
continue;
q.push(ed);
}
}
}
int main() {
while (gets(map[0]) != NULL ) {
gets(map[1]);
memset(vis,0, sizeof(vis));
// 对map数组进行初始化
for (int i = 0; i <= 1; i++) {
for (int j = 0; j <= 2; j++) {
if (map[i][j] == ' ') {
row = i;
col = j;
}
if (map[i][j] == 'A') {
row_a = i;
col_a = j;
}
if (map[i][j] == 'B') {
row_b = i;
col_b = j;
}
}
}
bfs();
}
return 0;
}