OJ_中国象棋中的跳马问题

中国象棋中的跳马问题

时间限制: 5 Sec
内存限制: 128 MB

题目描述

现在棋盘的大小不一定,由p,q给出,并且在棋盘中将出现障碍物(限制马的行动,与象棋走法相同)

输入

第一行输入n表示有n组测试数据。

每组测试数据第一行输入2个整数p,q,表示棋盘的大小(1<=p,q<=100)。
每组测试数据第二行输入4个整数,表示马的起点位置与终点位置。(位置的取值范围同p,q)
第三行输入m表示图中有多少障碍。
接着跟着m行,表示障碍的坐标。

输出

马从起点走到终点所需的最小步数。
如果马走不到终点,则输入“can not reach!”

样例输入

2
9 10
1 1 2 3
0
9 10
1 1 2 3
8
1 2
2 2
3 3
3 4
1 4
3 2
2 4
1 3

样例输出

1
can not reach!

提示

此题是一个搜索题,可用DFS或BFS,建议选择BFS(广搜)。一开始把马的起始点加入队列,然后用广搜的思想把此点能到达的其他点加入队列,这里需要一个数组用来记录此点在之前是否已经加入队列,如果加入过队列当中,就不需要再加入了,直到队列里的元素为空,或者搜索到了终点,搜索即停止,然后输出相应答案即可。

解题思路

在这里插入图片描述

答案

#include <bits/stdc++.h>

using namespace std;
struct Position
{
    int x;
    int y;
};
struct node
{
    int x;
    int y;
    int step;
};
int p, q ;
int block[101][101] = {0}; //记录障碍的坐标
int visited[101][101] = {0}; //标志是否已经访问
Position  move_delta[8] = {{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2}}; //马可以落脚的位置
Position  bar[8] =        {{-1,0},{-1,0},{0,1},{0,1},{1,0},{1,0},{0,-1},{0,-1}};   //绊马脚的位置

int in_chessboard(int x, int y)
{
    if( x > 0 && x <= p && y > 0 && y <= q)
        return true;
    return false;
}
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int step = 0, flag = 0;       //记录走的步数
        queue<node>que;
        memset( block, 0, sizeof(block) );
        memset( visited, 0, sizeof(block) );
        int Start_X, Start_Y, End_X, End_Y ;
        int i, n ;
        cin >> p >> q ;
        cin >> Start_X >> Start_Y >> End_X >> End_Y ;
        cin >> n ;
        for(i = 0 ; i < n ; ++i)
        {
            int x, y ;
            cin >> x >> y ;
            block[x][y] = 1 ;
            visited[x][y] = true;
        }

        node P = {Start_X, Start_Y, step}, Q;
        que.push(P);
        visited[Start_X][Start_Y] = true;

        while( !que.empty() )
        {P = que.front();
            int x = P.x;
            int y = P.y;

            que.pop();
            if(x == End_X && y == End_Y) //到达终点后退出
            {
                flag = 1;
                step = P.step;
                break;
            }
            for( i = 0 ; i < 8; ++i )
            {
                int new_x = x+move_delta[i].x;
                int new_y = y+move_delta[i].y;
                if( (in_chessboard( new_x, new_y)) && ( !block[new_x][new_y] ) && (!block[x+bar[i].x][y+bar[i].y]) && (!visited[new_x][new_y]) )
                {
                    //1.判断即将落脚的地方是否在棋盘内
                    //2.判断是否有障碍(能否落脚)
                    //3.判断是否绊马脚
                    //4.判断即将落脚的地方是否已经被访问过

                    Q = {new_x,new_y,P.step+1};
                    que.push(Q);
                    visited[new_x][new_y] = true;    //如果成功则更新信息

                }
            }
        }
        if(flag == 1)
            cout << step << endl ;
        if(!flag)
            cout << "can not reach!" << endl;
    }
    return 0;
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值