7-9 马跳的步数(C语言)

描述

在中国象棋中,棋子活动的场所,叫做"棋盘",在长方形的平面上,绘有九条平行的竖线和十条平行横线相交组成,共九十个交叉点,棋子就摆在这些交叉点上。中间第五、第六两横线之间未画竖线的空白地带,称为"河界",整个棋盘就以"河界"分为相等的两部分;两方将帅坐镇、画有"米"字方格的地方,叫做"九宫"。
中国象棋中,马是威力很大的棋子。马走动的方法是一直一斜,即先横着或直着走一格,然后再斜着走一个对角线,俗称"马走斜"。马一次可走的选择点可以达到四周的八个点,故有"八面威风"之说。
我们约定最左下角点的坐标为(0,0),则最右上角的坐标为(9, 8)。上图中马在坐标(2, 2)处。它走一步可以到达坐标点(1, 0),(0, 1),(0, 3),(1, 4),(3, 4),(4, 3),(4, 1)或(3,0)。如下图所示。

我们约定当前棋盘上只有一个马,给出起点坐标和终点坐标,求从起点到终点,马最少要走几步?

输入格式:

输入的的第1行是一个整数n,表示以后会有n行数据。
从第2行开始,每行有4个整数,前2个数表示起点坐标,后2个数表示终点坐标。

输出格式:

对每行起点和终点坐标输出一个整数,表示从起点到终点最少需要走的步数。每次输出之后换行。

输入样例:

在这里给出一组输入。例如:

2
2 2 5 2
0 0 9 8

输出样例:

在这里给出相应的输出。例如:

3
7

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

一、问题分析及算法设计思路

        该题的解法与第11题马走日是类似的,采用bfs算法递归棋盘上的每一个点,与第11题的区别是本题给定了终点,要求是从起点到终点的最短步数。我们需要改动的便是在递归的条件上加入最短路径的判断,当往后的步数超过了当前最小步数,就停止递归。当到达终点时,判断每个步数大小,若新的步数少于之前走的步数,就替换掉最小值min。

 

二、代码实现

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define true 1
#define false 0
#define MAX 20



//num是有多少走到终点的方式
int min = 32767;

int step = 1;
//最大棋盘的数组
int a[MAX][MAX];
//象棋挪动的方式
int move[8][2]= {{2,-1}, {1,-2}, {-1,-2}, {1,2}, {2,1}, {-2,-1}, {-2,1}, {-1,2}};
//广度优先遍历,输入出发点和结束点
void dfs(int x,int y,int x2,int y2)
{

    //x1,y1为暂时的位置
    int i, x1, y1;
    //当步数大于最小值的情况就不需要继续往下了
    if(step > min) return;
    //当便利了全部的结点,便可返回
    if(x == x2 && y == y2)
    {
        //成功递归一次证明有一种走完全部节点的可能性
        if(step <= min) min = step;
    }
    else
        //按照八种不同的方向走的情况
        for(i=0; i<8; i++)
        {
            //每次递归就移动一次
            x1 = x + move[i][0];
            y1 = y + move[i][1];
            //不能出棋盘,并且落点未被选中过
            if(x1 >= 0 && x1 < 10 && y1 >= 0 && y1 < 9 && a[x1][y1] == 0)
            {
                //选中该落点
                a[x1][y1] = true;
                //落点数+1
                step++;
                //递归调用
                dfs(x1, y1, x2, y2);
                //当一次结束递归时,让步数一步步返回至原点,并且开始下一种可能性的递归
                step--;
                //将上一次递归选中的点再依次设置为未选中
                a[x1][y1] = false;
            }
        }
}

int main()
{
    int T, x, y, x2, y2;
    scanf("%d", &T);
    while(T--)
    {
        step = 0;
        min = 32767;
        scanf("%d %d %d %d", &x, &y, &x2, &y2);
        memset(a, 0, sizeof(a));
        a[x][y] = 1;
        dfs(x, y, x2, y2);
        printf("%d\n", min);
    }
    return 0;
}

 三、测试点、

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百年bd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值