最短路径 && 白骑士的移动(BFS)

宽度优先搜索

在这里插入图片描述
在这里插入图片描述
*图片来源:挑战程序设计竞赛(第2版)

最短路径

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

http://m.blog.csdn.net/article/details?id=50768661。

#include <iostream>
#include <queue>
using namespace std;
const int MAX_N = 100;
const int MAX_M = 100;
const int INF = 0x3f3f3f3f;   //用来表示无穷大
typedef pair<int, int> P;   //定义一个坐标形式
char maze[MAX_N][MAX_M + 1];
int N, M;
int sx, sy; //起点的位置
int gx, gy; //终点的位置
 
int d[MAX_N][MAX_M];//储存起点到某一点的距离
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };  //移动方向
 
void bfs()
{
	queue<P> que;
	for (int i = 0; i < N; i++)
		for (int j = 0; j < M; j++)
			d[i][j] = INF;	     //将所有的点置空
	que.push(P(sx, sy));  //输入起点
	d[sx][sy] = 0;	    
 
	while (que.size())   //
	{
		P p = que.front(); que.pop(); //每一队都是一层(累积的距离相等),且只考虑一队
		int i;
		for (i = 0; i < 4; i++)		//输入目前这个点周围四个中没有被访问过的点
		{
			int nx = p.first + dx[i];
			int ny = p.second + dy[i];
			if (0 <= nx&&nx < N
				&& 0 <= ny&&ny < M
				&&maze[nx][ny] != '#'
				&&d[nx][ny] == INF)
		/*如果这个点(那四个点之一)
		1.在这个地图内
		2.这个点不是‘#’(不是墙)
		3.其值等于无穷大(未被访问过)
		*/
			{
				que.push(P(nx, ny));//满足以上条件即可进入队列
				d[nx][ny] = d[p.first][p.second] + 1; //目标位置下移了一次
				if(nx==gx && ny==gy) break;  //到了终点
 
                        }
		}
		if(i!=4) break;
	}
 
}
 
int main()
{
	cin>>N>>M;
	for (int i = 0; i < N; i++)
		cin>>maze[i];
	for (int i = 0; i < N; i++)
		for (int j = 0; j < M; j++)
		{
			if (maze[i][j] == 'S')
			{
				sx = i; sy = j;
			}
			if (maze[i][j] == 'G')
			{
				gx = i; gy = j;
			}
		}
	bfs();
	cout<<d[gx][gy]<<endl;
 
	return 0;
}

7-3 白骑士的移动 (20分)

小S第一次接触国际象棋。他发现国际象棋中的Knight棋子的移动方式和中国象棋中的马类似,移动方式如图所示。 QQ图片20191115182554.png

于是小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
#include <iostream>
#include <queue>

using namespace std;

const int M = 8;
const int N = 8;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> P; //定义一个坐标形式
char MAP[M][N + 1];
int sx, sy;
int ex, ey;

int d[M][N];
int dx[8] = {-2, -1, 1, 2, -2, -1, 1, 2}, dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};

void read_mark();
void bfs();

int main()
{

    read_mark();
    bfs();
    if(d[ex][ey] != INF)
    cout << d[ex][ey] << endl;
    else
    {
        cout << "Checkmate" << endl;
    }
    
}

void read_mark()
{
    for (int i = 0; i < M; i++)
        for (int j = 0; j < N; j++)
        {
            cin >> MAP[i][j];
        }

    for (int i = 0; i < M; i++)
        for (int j = 0; j < N; j++)
        {
            if (MAP[i][j] == 'K')
            {
                sx = i;
                sy = j;
            }

            if (MAP[i][j] == 'Q')
            {
                ex = i;
                ey = j;
            }

            if (MAP[i][j] == 'R') //战车攻击范围
                {
                    for (int ii = 0; ii < 8; ii++)
                {
                    if(MAP[i][ii] == 'Q' ||( MAP[i][ii] == 'R' && ii !=j) ||MAP[i][ii] == 'B' )
                        {break;}
                    else{
                        MAP[i][ii] = 'x';
                        
                    }
                     
                }
                for (int ii = 0; ii < 8; ii++)
                {
                    if(MAP[ii][j] == 'Q' ||MAP[ii][j] == 'B'||( MAP[ii][j] == 'R' && ii !=i))
                        break;
                    else {MAP[ii][j] = 'x';}
                }
                }
            

            if (MAP[i][j] == 'B') //主教攻击范围
            {
                
                int I = i+1, J = j+1;
                while (I < M && J <N && I >= 0 && J >= 0 && MAP[I][J] != 'B'&& MAP[I][J] != 'R'&& MAP[I][J] != 'Q')
                { MAP[I++][J++] = 'x';};
                
                I = i-1;J = j-1;
                while (I < M && J < N && I >= 0 && J >= 0 && MAP[I][J] != 'B'&& MAP[I][J] != 'R'&& MAP[I][J] != 'Q')
                {MAP[I--][J--] = 'x';};

                I = i-1;J = j+1;
                while (I < M && J < N && I >= 0 && J >= 0 && MAP[I][J] != 'B'&& MAP[I][J] != 'R'&& MAP[I][J] != 'Q')
                {MAP[I--][J++] = 'x';};

                I = i+1;J = j-1;
                while (I < M && J < N && I >= 0 && J >= 0 && MAP[I][J] != 'B'&& MAP[I][J] != 'R'&& MAP[I][J] != 'Q')
                {MAP[I++][J--] = 'x';};
            }
        }
    /*for (int i = 0; i < N; i++)
        {putchar('\n');
		for (int j = 0; j < M; j++)
        cout<<MAP[i][j];}*/
}

void bfs()
{
    queue<P> que;
	for (int i = 0; i < N; i++)
		for (int j = 0; j < M; j++)
			d[i][j] = INF;
   que.push(P(sx, sy));  //输入起点
	d[sx][sy] = 0;	  

    while (que.size())  
	{
		P p = que.front(); que.pop();
		int i;
		for (i = 0; i < 8; i++)		
		{
			int nx = p.first + dx[i];
			int ny = p.second + dy[i];
			if (0 <= nx&&nx < N
				&& 0 <= ny&&ny < M
				&& MAP[nx][ny] != 'x'
                && MAP[nx][ny] != 'B'
                && MAP[nx][ny] != 'R'
				&& d[nx][ny] == INF)
			{
				que.push(P(nx, ny));
				d[nx][ny] = d[p.first][p.second] + 1; 
				if(nx==ex && ny==ey) break; 
 
            }
		}
		if(i!=8) break;
	}
 
}
/*
R...R..Q
B.......
........
........
........
........
........
....K...

*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值