目录
白骑士的移动
小S第一次接触国际象棋。他发现国际象棋中的Knight棋子的移动方式和中国象棋中的马类似,移动方式如图所示。
于是小S在棋盘上随意摆上了一些棋子,其中包括一枚白骑士、一枚黑皇后、若干黑战车和若干黑主教。
小S想知道,如何能在避开黑战车和黑主教的攻击范围的前提下,花费更少的步数吃掉黑皇后。
注1:战车的攻击范围呈直线,和中国象棋的車类似;主教的攻击范围呈斜线,无障碍物情况下可无限延伸。
注2:白骑士只能吃黑皇后,不可以吃掉黑战车和黑主教。
输入格式:
输入仅包含一组样例。
一组样例包含8行(分别对应1-8行),每行包含8个字符,每个字符代表对应行对应列的棋盘格子状况。
其中' . '代表格子上没有摆放任何棋子;' K '代表格子上摆放的是白骑士; ' Q '代表格子上摆放的是黑皇后; ' R '代表格子上摆放的是黑战车; ' B '代表格子上摆放的是黑主教。
注:题目保证白骑士的初始位置不在黑战车和黑主教的攻击范围内。
输出格式:
如果白骑士可以在避开黑战车和黑主教的攻击的情况下吃掉黑皇后,则输出花费步数的最小值;否则输出"Checkmate"。
输入样例1:
R.B.QB.R
........
........
........
........
........
........
.K......
输出样例1:
4
输入样例2:
....RR.Q
........
.K......
........
........
........
........
........
输出样例2:
Checkmate
注意点:要注意初始化时,黑战车和黑主教的攻击范围,当遇到棋子时,这个棋子后面就无法攻击到了
还有黑主教是如何斜着攻击的,横坐标和纵坐标同时加或同时减,或者一个加,一个减,遇到棋子时停止即可
整体用的是广度优先遍历的思想来求解
ac代码:
#include<iostream>
#include<queue>
using namespace std;
char a[10][10]; //存放棋盘
int v[10][10]={0}; //标记是否入过队列
int ZL[8][2] = {-2,-1, -2,1, 2,-1, 2,1, -1,-2, -1,2, 1,-2,1,2}; //增量
struct node{
int x,y,step;
}s,t;
int bfs(int x1,int y1){
queue<node> q;
s.x = x1;
s.y = y1;
s.step = 0;
q.push(s);
v[x1][y1] = 1;
while(!q.empty()){
t = q.front();
q.pop();
s.step = t.step +1;
for(int i=0;i<8;i++){
s.x = t.x + ZL[i][0];
s.y = t.y + ZL[i][1];
if(s.x>=0 && s.y>=0 && s.x<8 && s.y<8 && !v[s.x][s.y]){
if(a[s.x][s.y]=='.'){
v[s.x][s.y] = 1;
q.push(s);
}else if(a[s.x][s.y] == 'Q'){
return s.step;
}
}
}
}
return 0;
}
int main()
{
int k,x1,y1;
int x,y,x2,y2;
for(int i=0;i<8;i++){
scanf("%s",a[i]);
}
for(int i=0;i<8;i++){ //初始化
for(int j=0;j<8;j++){
if(a[i][j]=='R'){ //黑战车
for(k=i+1;k<8;k++){
if(a[k][j]=='.')
a[k][j]='a';
else break; //遇到人时停
}
for(k=i-1;k>=0;k--){
if(a[k][j]=='.')
a[k][j]='a';
else break;
}
for(k=j+1;k<8;k++){
if(a[i][k]=='.')
a[i][k]='a';
else break;
}
for(k=j-1;k>=0;k--){
if(a[i][k]=='.')
a[i][k]='a';
else break;
}
}else if(a[i][j]=='B'){ //黑主教
for(x=i+1,y=j+1;x<8,y<8;x++,y++){
if(a[x][y]=='.')
a[x][y]='a';
else break; //遇到人时停
}
for(x=i-1,y=j-1;x>=0,y>=0;x--,y--){
if(a[x][y]=='.')
a[x][y]='a';
else break;
}
for(x=i+1,y=j-1;x<8,y>=0;x++,y--){
if(a[x][y]=='.')
a[x][y]='a';
else break;
}
for(x=i-1,y=j+1;x>=0,y<8;x--,y++){
if(a[x][y]=='.')
a[x][y]='a';
else break;
}
}
else if(a[i][j]=='K'){ //记录白骑士的下表
x1=i;y1=j;
}
}
}
int t=bfs(x1,y1);
if(t) printf("%d",t);
else printf("Checkmate");
return 0;
}
广搜(BFS)的伪代码
void BFS(int s){
queue<int> q;
q.push(s);
while(!q.empty()){
取出队首元素
访问队首元素
将队首元素出队
将top的下一层节点中未曾入队的节点全部入队,并设置为已入队
}
}