《程序员》2007年第九期算法擂台——骑士聚会

问题:
    在8×8的棋盘上分布着n个骑士,他们想约在某一格的中聚会,骑士每天可以像国际象棋中的马那样移动一次,如下图所示,可以从中间向8个方向移动,请你计算n个骑士的最早聚会地点和要走多少天。要求尽早聚会,且n个人走的总步数最少,先到聚会地点的骑士可以不再移动等候其他骑士。
    从键盘输入n(0<n<=64),然后依此输入n个骑士的初始位置xi,yi(0<=xi,yi<=7)。屏幕输出以空格分隔的三个整数,分别为聚会点的x,y值,以及要走多少天。

    ○     ○  
  ○
        ○
     ★    
  ○         ○
    ○    ○  



     问题很是复杂,所以要先从特殊的简单的入手,我们先考虑一个骑士从某点到达另一点的最少天数,然后我们就可以考虑每个骑士到达指点地点自身所耗费的时间,最好,考虑棋盘上64个格子,那个是他们的聚会地点。
     可见,问题最困难的地方是第一步,如何求解从某点到达另外一点的最短路径。在此我想到了吕震宇老师的关于华容道的系列blog,所以想到了用树来解决这个难题。
  1. 对于任何一个骑士来说,第一步有最多8种选择,当走到第二步时路径就会是8×8=64(这是最多的情况),第三步最多是64×8=512种,……(哇塞,这个数字增长的好恐怖啊)~!
  2. 通过图片我们可以看到,我在树的每一层中穿了一根线,这根线的作用就是要便利所有的可能路线,检查是否已经到达了目的地,因为他囊括了所有的可能,而且每走一步就会检查一下是否到达目的地。
  3. 按照以上两步可以在第一时间尽早的发现最短的时间(也即最短的路径)。



下面是核心代码,用以计算此匹马到地图上某点(endPoint)所用的最少天数:
 1         public int GetMinDays(Point endPoint)
 2         {
 3             Dictionary<int, List<Node>> level = new Dictionary<int,List<Node>>();
 4             List<Node> header = new List<Node>();
 5             header.Add(new Node(startPoint.X, startPoint.Y));
 6             int l = 0;
 7             level.Add(l, header);
 8 
 9             while (true)
10             {
11                 foreach (Node node in level[l])
12                 {
13                     if (node.IsEquals(endPoint))
14                     {
15                         return l;
16                     } 
17                 }
18 
19                
20                 List<Node> tempList = new List<Node>();
21                 foreach (Node node in level[l])
22                 {
23 
24                     for (int i = 0; i < 8; i++)
25                     {
26                         Point nextPoint = MoveToNextPoint(node.current, i);
27                         if (nextPoint != null)
28                         {
29                             node.children[i] = new Node(nextPoint.X, nextPoint.Y);
30                             tempList.Add(node.children[i]);
31                         }
32                     }
33                 }
34 
35 
36                 level.Add(++l, tempList);
37             }
38         }

其中level是每层的那条线。



好了,把源代码放上来:knightParty.rar

posted on 2007-09-11 21:19  啊不才  阅读(715)  评论(6编辑  收藏  举报

导航