http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1091
编程任务:输入两个方格a和b,确定骑士在最短路径上从a到b移动的次数
算法分析:
1、 最容易想到就是深度优先搜索了,从起点向八个方向递归求解,计算起点到各个点的最短路径,但是深搜速度慢,如果棋盘大的话, 很容易就超时了
2、 然后就是广度优先搜索了,从起点进行8个方向的搜索,搜索到终点即结束
3、 觉得这个方法确实比较好,如果让我想估计想不到:棋盘是8*8的,在任意一个方格,骑士都可以走到棋盘上的任意其他方格,这样就有64种可能;因为有64格,所以要保存任意两格之间的最短路径的步数,需要64*64的数组。 int Knight[64][64];
建立64*64的矩阵数组与棋盘之间的对应关系。设矩阵数组的单元(i,j)(0=<i,j<=63),对应棋盘上的骑士从方格a(i/8,i%8)跳到方格b(j/8,j%8),如果只需要走一步则为1,否则为无穷:方格自身为0
设(x,y)为方格a和b之间的坐标差值,计算公式:简化代码,用abs()函数表示
x = i/8 – j/8; x = abs(i/8 – j/8);
y = i%8 – j%8; y = abs(i%8 – j%8);
在棋盘上(x,y)的相对位置有8个方向,如图阴影单元格
|
(-1,2) |
|
(1,2) |
|
(-2,1) |
|
|
|
(2,1) |
|
|
(0,0) |
|
|
(-2,-1) |
|
|
|
(2,-1) |
|
(-1,-2) |
|
(1,-2) |
|
可以看到,当x变化为1时y变化为2,或者x变化为2时y变化为1
所以就有: if(x == 1 && y == 2 || x == 2 && y == 1) Knight[i[j] = Knight[j][i] = 1;
然后采用floyd算法求出所有单元格的最短路径
深搜:
#include<string.h> #include<stdio.h> #define MAXN 9 int dir[8][2] = {-1,-2, -2,-1, -2,1, -1,2, 1,2, 2,1, 2,-1, 1,-2}; int ans[MAXN][MAXN]; void dfs(int si,int sj,int moves) { if(si<1||si>8||sj<1||sj>8||moves>=ans[si][sj]) return ; ans[si][sj] = moves; //最优解 int i; for(i=0;i<8