洛谷P1747 好奇怪的游戏

此题源于洛谷P1747
链接奉上qwq:P1747
题目背景
《爱与愁的故事第三弹·shopping》娱乐章。
调调口味来道水题。
题目描述
爱与愁大神坐在公交车上无聊,于是玩起了手机。一款奇怪的游戏进入了爱与愁大神的眼帘:***(游戏名被打上了马赛克)。这个游戏类似象棋,但是只有黑白马各一匹,在点x1,y1和x2,y2上。它们得从点x1,y1和x2,y2走到1,1。这个游戏与普通象棋不同的地方是:马可以走“日”,也可以像象走“田”。现在爱与愁大神想知道两匹马到1,1的最少步数,你能帮他解决这个问题么?
输入输出格式
输入格式:
第1行:两个整数x1,y1
第2行:两个整数x2,y2
输出格式:
第1行:黑马到1,1的距离
第2行:白马到1,1的距离
输入输出样例
输入样例#1:
12 16
18 10
输出样例#1:
8
9
说明
100%数据:x1,y1,x2,y2<=20

这道题目吧
这里写图片描述
2333333黄色难度?哇好难啊qwq
然后我就过了(装13时间)

【分析】
题意说是可以走田也可以走日,那么就说明有12个方向:

int dx[12]={2,-2,2,-2,1,1,-1,-1,2,2,-2,-2};//横坐标添加
int dy[12]={2,2,-2,-2,2,-2,2,-2,1,-1,1,-1};//纵坐标添加

还有这道题就是明显的BFS啊…
DFS和BFS在选择算法的最大区别就是:
DFS主要是在让你求所有的结果时多用
而BFS则是让你求一个最优解所用(因为BFS一层一层搜索,肯定最后是最优解)
这道题也一样的,从题干能够看出,是让求两匹马到1,1的最少步数。
最少最少最少!

【思路】
从马开始所在的坐标开始搜索,搜索这个点到每一个点的最短步数。最后输出1,1这个坐标点的最短步数就OK了。
而且如果我们自己在图上推如何去求最短步数便可得(推导过程略,自力更生丰衣足食)
当前的结点的父节点+1的值,因此便可以直接使用BFS进行移动,然后把12个方向分别分成这一行的当前节点的12的子节点(如果12个方向符合不超出边界且没走过的情况),然后依次向下,直到所有的都过一遍。
PS:我觉得这样讲有点晕,但是真的就是这样,仔细推敲一下就可以了。

【代码】

#include <stdio.h>
#include <string.h>
int dx[12]={2,-2,2,-2,1,1,-1,-1,2,2,-2,-2};
int dy[12]={2,2,-2,-2,2,-2,2,-2,1,-1,1,-1}; //横纵坐标的方向 
int b[1001][1001],que[100001][3],a[1001][1001]; //b为判断是否走过,que为队列,a为最少步数 
int BFS(int x,int y)
{
    int tail=1,head=0;
    que[tail][0]=x;
    que[tail][1]=y;
    b[x][y]=1;   //初始化,第一个结点,即马的初始坐标先入队列 
    do
    {
        head++;
        for (int i=0;i<12;i++)
        {
            int x1=que[head][0]+dx[i]; //位置转换后的横坐标 
            int y1=que[head][1]+dy[i];  //位置转换后的纵坐标 
            if (x1>=1 && x1<=50 && y1<=50 & y1>=1 && b[x1][y1]==0)  //如果不出边界且这个地方没走过的话 
            {
                tail++; 
                que[tail][0]=x1;
                que[tail][1]=y1; //将新的结点入队列 
                b[x1][y1]=1;    //标记走过 
                a[x1][y1]=a[que[head][0]][que[head][1]]+1; //原本坐标的最少步数移了一步即为移动后坐标的步数 
            }
        }
    }while (head<tail);    //如果队列不为空 
    return a[1][1]; //最后调用a[1][1]即为1,1的最短路径 
}
int main()
{
    int x1,y1,i,j;
    scanf("%d%d",&x1,&y1); //输入第一个马的坐标 
    printf("%d\n",BFS(x1,y1)); //输出搜索的值 
    memset(b,0,sizeof(b)); 
        memset(que,0,sizeof(que));
            memset(a,0,sizeof(a)); //注意!!!这里我被坑了!一定要把所有再赋为初值! 
scanf("%d%d",&x1,&y1);  //输入第二个马的值 
printf("%d\n",BFS(x1,y1)); //输出搜索的值 
return 0;
}

【反思及注意点】
有个地方需要注意,就是在搜索时的边界,因为是要把所有的点都搜索一遍,所以就变成一个最大值,这里看了讨论区大佬所述!万分感谢!

我在想这道题目时有个地方有点卡壳,就是在

a[x1][y1]=a[que[head][0]][que[head][1]]+1;

这里我原本写的是

a[x1][y1]=que[head][2]+1;

这里的que[head][2]当前节点的步数,但是这时发现这样写莫名不对,然后就一直改,最后发现是因为有BUG,也是自己脑子抽筋了,因为这样写的话你的que[head][2]并没有赋上值,所以一直都0。

这里就是蒟蒻题解的全部内容,望各位多多关照!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值