资源限制
时间限制:1.0s 内存限制:256.0MB
你玩过华容道的游戏吗?
这是个类似的,但更简单的游戏。
看下面 3 x 2 的格子
+---+---+---+
| A | * | * |
+---+---+---+
| B | | * |
+---+---+---+
在其中放5张牌,其中A代表关羽,B代表张飞,* 代表士兵。
还有一个格子是空着的。
你可以把一张牌移动到相邻的空格中去(对角不算相邻)。
游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。
输入格式
输入两行6个字符表示当前的局面
输出格式
一个整数,表示最少多少步,才能把AB换位(其它牌位置随意)
例如,输入:
* A
**B
程序应该输出:
17
再例如,输入:
A B
***
程序应该输出:
12
资源约定:
峰值内存消耗 < 256M
CPU消耗 < 1000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。
所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。
提交时,注意选择所期望的编译器类型。
思路
最少步数,不难想到BFS。由于此题只要求AB位置互换,且只有一个空白格,那么状态就只和空白格,A,B的坐标有关。因为数据量很小,是2x3矩阵。可以用一个六维数组来标记每一个状态,确保空白格,A,B三者的坐标组成独一无二的状态。
int vis[5][5][5][5][5][5];//状态只取决于空白格和A,B的坐标,用此标记此状态是否出现过
接下来就是利用结构体来描述状态
struct blank {
int x, y;//空白格的坐标
int step,ax,ay,bx,by;//现在的步数,a和b的坐标
};
录入数据时,确定好空白格,A,B的坐标。且作为初始状态入队
queue<blank>q;
blank t = { sx,sy ,0,A.first,A.second,B.first,B.second};
q.push(t);//初始状态入队
vis[sx][sy][t.ax][t.ay][t.bx][t.by] = 1;//标记此状态
自定义check函数,用来检查每个状态下A,B是否实现互换。注意每个状态下的空白格,A,B坐标,所确定的状态都是独一无二且第一次出现的,保证第一次搜索到便是最小步数。
int check(int tax,int tay,int tbx,int tby) {
if (tax==B.first && tay == B.second && tbx == A.first && tby == A.second)
return 1;
return 0;
}
搜索时注意,以为空白格为媒介,每次是空白格进行上下左右尝试交换,如果空白格即将到达的位置是上个状态的A或B的位置,便及时更新此状态下的A或B位置。然后及时check。
最后说明一下,蓝桥杯练习系统有一组数据并没有空白格,是数据错误。此题解进行了特判,可AC。
测试详情和错误数据
Code
#include<bits/stdc++.h>
using namespace std;
char a[5][5];
pair<int,int>A,B;
int wk[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };//下右上左四个方向
int sx,sy;
int vis[5][5][5][5][5][5];//状态只取决于空白格和A,B的位置
struct blank {
int x, y;//空白格的坐标
int step,ax,ay,bx,by;//现在的步数,a和b的坐标
};
int check(int tax,int tay,int tbx,int tby) {
if (tax==B.first && tay == B.second && tbx == A.first && tby == A.second)
return 1;
return 0;
}
void bfs() {
queue<blank>q;
blank t = { sx,sy ,0,A.first,A.second,B.first,B.second};
q.push(t);//初始状态入队
vis[sx][sy][t.ax][t.ay][t.bx][t.by] = 1;
while (!q.empty()) {
blank u = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int tx = u.x + wk[i][0], ty = u.y + wk[i][1];//空格即将和tx,ty交换
int tax = u.ax, tay = u.ay, tbx = u.bx, tby = u.by;
if (tx < 1 || tx>2 || ty < 1 || ty>3 || vis[tx][ty][tax][tay][tbx][tby])continue;
t.x = tx, t.y = ty, t.step = u.step + 1;//新状态,空格的位置将在tx,ty
t.ax = u.ax, t.ay = u.ay, t.bx = u.bx, t.by = u.by;
if (tx == u.ax && ty == u.ay) {//如果空格要和A交换,空格原来位置u.x,u.y
t.ax = u.x, t.ay = u.y;
tax = t.ax, tay = t.ay;
}
else if (tx == u.bx && ty == u.by) {//如果空格要和B交换
t.bx = u.x, t.by = u.y;
tbx = t.bx, tby = t.by;
}
vis[tx][ty][tax][tay][tbx][tby] = 1;//标记此状态
if (check(tax,tay,tbx,tby)) {
printf("%d", t.step);
exit(0);
}
else
q.push(t);
}
}
}
int main(){
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= 3; j++) {
cin.get(a[i][j]);
if (a[i][j] == 'A')A.first = i, A.second = j;
if (a[i][j] == 'B')B.first = i, B.second = j;
if (a[i][j] == ' ')sx = i, sy = j;
}
getchar();
}
if (sx == 0 && sy == 0)printf("10");//蓝桥杯练习系统有一组数据错误,没有空白格
else bfs();
return 0;
}