queensf
总版主
总版主
  • 注册日期2003-12-04
  • 发帖数735
  • QQ
  • 铜币3枚
  • 威望0点
  • 贡献值0点
  • 银元0个
阅读:2710回复:2

相邻项序列

楼主#
更多 发布于:2004-02-21 15:21
相邻项序列

 问题描述:

对于一个N*N(N≤100)的正整数矩阵M,存在从M[A1,B1]开始到M[A2,B2]结束的相邻项序列。两个项M[I,J]和M[K,L]相邻的条件是指满足如下情况之一:(1)I=K±1和J=L;(2)I=K和J=L±1。先要求你从文件中读入矩阵M及K(K≤4)组M[A1,B1]和M[A2,B2],求一相邻项序列,使得相邻项之差的绝对值之和为最小。

输入格式及样例:
4                  //表示矩阵M的大小      

1   9   6   12     //每行有M个数据,共M行

8   7   3   5

5   9   11  11

7   3   2   6

2                  //表示有K组数据

4   1   1   4      //表示A1,B1及A2,B2的值,共K行

2   2   3   4

  

输出格式及样例:

1  17               //表示第1组数据相邻项之差的绝对值之和的最小值为17

7  5  8  7  9  6  12    //表示第1组数据的相邻序列

2  4                 //表示第2组数据相邻项之差的绝对值之和最小值为4

7  9  11  11          //表示第2组数据的相邻序列

 
 
算法分析:

本题若将相邻的两个数看成是两个顶点,两个数差的绝对值作为权,则问题转化为图论中的求两顶点间的最短路问题。

对于有向图D=(V,A),弧a=(Vi,Vj),相应地有权W(a)=Wij,对有向图D中两个顶点Vs,Vt,设P是D中从Vs到Vt的一条路,定义路P的权是P中所有弧的权之和,记作W(p),所谓最短路问题就是在所有从Vs到Vt的路中,找出一条权最短的路,即求一条从Vs到Vt的路P0,令:

           W(P0)=min(p)

对于所有Wij>=0,即所有的权为非负值时,求最短路通常使用标号法。

所谓标号法的基本思想是从Vc出发,逐步地向外探寻最短路。在执行过程中,与每个点对应,记录下一个数(称为这个点的标号),它或者表示从Vs到该点的最短路的权(称为P标号),或者表示这个权的上界(称为T标号),具体做法是每扩展一步,就将一个具T标号的点改具P标号的点,从而使有向图D中具P标号的顶点数增多一个。如此一步步执行下去,就可求出从Vs到各点的最短路。

为简便起见,我们可以称从M[I,J]到M[K,L]的相邻项之差的绝对值之和最小的相邻项序列为从M[I,J]到M[K,L]的“最优序列”。这样便可用标号法来求得从起点M[A1,B1]到矩阵M的其它各项的“最优序列”。

设SUM[I,J]为从M[A1,B1]到M[I,J]的“最优序列”的相邻项的绝对值之和。有:

SUM[I,J]=MIN SUM[K,L]+ABS(M[I,J]-M[K,L]){I=K±1且J=L,或I=K且J=L±1}

通过这一式子,可以利用标号法来求得从M[A1,B1]到M[A2,B2]的最优序列。

在标号法中,每一次扩展都要寻找一个项M[I,J],其中:

① M[I,J]是未改为P的标号的点;

② SUM[I,J]=MIN SUM[K,L]{K,L∈[1,N],且M[K,L]是未改为P标号的点。

这一步若采用二重循环来求则非常耗时。所以考虑采用一个队列来存储矩阵中待扩展的项,使得该队列的各项的SUM值地由小到大排列的。扩展时,只要移动队列的首指针即可:生成的新的待扩展的项,可以将其插入到队列中的适当位置,使插入后队列的各项的SUM值仍是从小到大排列。为了较方便地插入新的待扩展的项,采用指针结构来存储这个队列。

具体算法描述:

  定义一个POINT类型来记录待扩展的项:

   point=^xy;

xy=record

   x,y:byte;

   next:point;

end;

其中X,Y为该项在矩阵中的坐标,NEXT为指针类型,以记录其在队列中的后继结点。

1、  置SUM[I,J]为∞(I<>A1或J<>B1),置SUM[A1,B1]为0;

2、  首指针F后移一位;

3、  若F^.X=B2且F^.Y=A2,则已找到从M[A1,B1]到M[A2,B2]的“最优序列”,反向链接、打印所经过的路径并转6,否则继续4;

4、  从M[F^.Y,F^.X]向上下左右四个方向扩展,现设向M[NODE1^.Y,NODE1^.X](NODE1^.Y=F^.Y±1且NODE1^.X=F^.X,或NODE1^Y=F^.Y且NODE1^.X=F^.X±1)扩展:

a)     SUM1:=SUM[F^.Y,F^.X]+ABS(M[F^.Y,F^.X]-M[NODE1^.Y,NODE1^.X]);

b)      若SUM1<SUM[NODE1^.Y,NODE1^.X],则继续c),否则转为4;

c)      SUM[NODE1^.Y,NODE^.X]:=SUM1;

d)      M[F^.Y,F^.X]是M[NODE1^.Y,NODE1^.X]的前趋项,记下从M[NODE1^.Y,NODE1^.X]到M[F^.Y,F^.X]的方向,以便打印时反向链接所经路径;

e)       生成一新待扩展结点NODE2,使得NODE2^=NODE1^,并把NODE2插入到队列中,使得插入后队列的各项的SUM值仍是从小到大排列;

5、  转2;

6、  结束


 
 

<img src="images/post/smile/dvbbs/em04.gif" /><img src="images/post/smile/dvbbs/em04.gif" /><img src="images/post/smile/dvbbs/em04.gif" /><img src="images/post/smile/dvbbs/em04.gif" /><img src="images/post/smile/dvbbs/em04.gif" /><img src="images/post/smile/dvbbs/em04.gif" />
喜欢0 评分0
[color=blue][size=4][i][b][u] 【 解决不了的事情,就不要想。世界不会因为我而改变。 】 [/size][/u][/b][/i][/color]
92412
路人甲
路人甲
  • 注册日期2004-05-19
  • 发帖数115
  • QQ
  • 铜币280枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2004-06-22 21:19
<P>斑竹的数据结构学得真好</P>
<P>佩服佩服!</P>

举报 回复(0) 喜欢(0)     评分
jinyu1123
路人甲
路人甲
  • 注册日期2006-07-05
  • 发帖数67
  • QQ
  • 铜币262枚
  • 威望0点
  • 贡献值0点
  • 银元0个
2楼#
发布于:2007-11-22 20:54
<img src="images/post/smile/dvbbs/em05.gif" />
迷茫啊! Email : jinyu1123@163.com.
举报 回复(0) 喜欢(0)     评分
游客

返回顶部