先看一个比较复杂的例子
上面的路线其实可以拆分成几个部分
可以看到我们将整个路线拆分成了3个环,最外面的环是一个6×5的矩形环 内侧是一个4×3的矩形环,最内侧是一个2×1的矩形环(这已经不是环了)。
每个环对应的步数是好计算的,对于一个n×m的环一共有n×m-4个格子,也就是步数为n×m-4。
而每个环对应的起点也是显然的,最外层的环起点是(1,1),内层的是(2,2),最内层是(3,3),从最外层数起,第i层的起点是(i,i)。这个起点是必要的准备工作。
对于给定的坐标(x,y),我们是可以知道其在哪一个环上的。假设就在第一层环上,该环为n*m的矩形环,无非就是在最外边的四个边上面,那么一定有 (x==1||x==n||y==1||y==m)
为真,否则就应该在里面的某一层。
当判断坐标不在最外层,想要找找看是不是在里面那层时,就接着判断
(x==2||x==n-1||y==2||y==m-1)
是否为真
稍微改下就是(x-1==1||x-1==n-2||y-1==1||y-1==m-2)
,为了方便就这么处理了下。稍微循环几次就能找到坐标在第几层了。
然后知道在第i层之后,我们只要再知道从该层的起点到坐标(x,y)的步数即可。那么问题为在一个左下角的点为(i,i),右上角的点为(n-i+1,m-i+1)构成的矩形环上找一个 (x,y),记下其到(i,i)的步数
这时可以将整问题的坐标系向左下平移为,在一个左下角的点为(1,1),右上角的点为
(n-2i+2,m-2i+2)构成的矩形环上找一个 (x-i+1,y-i+1)的点,记下其到(1,1)的步数,这就相对而言好算一些。
最后的部分
我们已经将所有的找环上具体位置的问题化简为了如下的问题
在n*m的矩形环上找(x,y)到(1,1)的步数
y=1时,在最下面的边上,步数:x
x=n时,在最右边的边上,步数:n+y-1
y=m时,在最上面的边上,步数:2n + m - x - 1
x=1时,在最左边的边上,步数:2m + 2n - y - 2
后面两个需要稍微 想下
最终的递归函数
int solve(int n, int m, int x, int y)
{
if (y == 1)
return x;
if (x == n)
return n + y - 1;
if (y == m)
return 2 * n + m - x - 1;
if (x == 1)
return 2 * m + 2 * n - y - 2;
//路线可以化成一个个相互嵌套的环
// 如果在圈上则会满足上述条件之一,然后根据x,y确定具体位置
//从而获得步数即可
return solve(n - 2, m - 2, x - 1, y - 1) + m * 2 + n * 2 - 4;
//若在不该环上则继续找里面一层的环,并加上该环的步数
}