洛谷P1747 好奇怪的游戏(真的很奇怪哦~)

来源:互联网 发布:本地pubmed数据库 编辑:程序博客网 时间:2024/06/06 16:42

此题源于洛谷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。

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

原创粉丝点击