回 帖 发 新 帖 刷新版面

主题:《折线》

〖题目描述〗
  给定m*n方格,某些方格内不可通行,求左上到右下最短路。

〖基本算法〗
  本题使用动态规划求解。
  记f(x,y)为从(0,0)走到(x,y)的最短路的长度,有
f(x,y)= min {f(i,j)+ sqrt(sqr(x-i)+ sqr(y-j)),格子(i,j)不在(x,y)右或下方且可直达};
  特别的,f(0,0)= 0;
  算法的复杂度为O(m^3 * n^3)。

〖优化〗
  上面这个算法是极其浪费的。事实上,可以很容易证明,如果一条路径有一个"拐弯"的地方不是某个障碍的左下或右上角,这条路一定不是最短路(下图)。所以我们可以对动态规划算法做个优化:
  f(x,y)= min {f(i,j)+ sqrt(sqr(x-i)+ sqr(y-j)),格子(i,j)不在(x,y)右或下方且可直达且格子(i,j)位于某个障碍的左下或右上角};
  另外我们只对障碍左下或右上角的格点及终点求f(x,y)。
  这样改进以后算法的复杂度为O(m * n * w^2)(w为障碍数),时间效率是很高的了。
  当然,本题还有很多优化方法,比如旋转坐标轴,然后仅对"最近的"障碍扫描等等

回复列表 (共2个回复)

沙发

在我看来是一个迷宫问题
而要解出最短路径
可以设两个栈a,b,足够大的数组a,b两个也行.a保存当前最短路径mincount为最短路径长.
b保存正在求的路径.栈尾保存路径长即count,求出后比较a,b路径长大小, a保存最短的,如此继续...最后a中的便是最短路径

迷宫的算法可以这样描述:
设全局的mark[m][n]作为迷宫相应路径位置的标志数组
栈a,栈b,计数器count,mincount.


search(int i,int j)
{
  
  if(++count==mincount)
     {count--;
      return;
     }/*不再是最短无需考虑*/
       
  i,j入栈,做好相应的标志;

  如果(i,j)为出口{
                找到一个解,并按上面的方法处理栈a,栈b;count--;去掉标记,(i,j)出 栈;
                return;
                }
  否则从(i,j)不同的方向寻找路径
      {
        如果没越界并且是通路而且没被做上标记search(i+x,j+y)((i+x,j+j)是(i,j)的某一相邻方向的路径的坐标;)
      }
  (i,j)出栈,去掉标记,count--;
return;
}     

标志位的作用是避免走重复的道.甚至是死循环.
希望我没漏写些啥.

板凳

不好意思,二位,非常佩服你们,可不可以把完整程序贴出来……我实在是搞不懂:(

我来回复

您尚未登录,请登录后再回复。点此登录或注册