此题源于洛谷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。
这里就是蒟蒻题解的全部内容,望各位多多关照!