目錄
白騎士的移動
小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的下一層節點中未曾入隊的節點全部入隊,並設置爲已入隊
}
}