Coding with .NET

Live with passion, coding with passion....

首页 新随笔 联系 订阅 管理

周末闲来无事,忽然想起大学时候学《数据结构》时候的期末上机考试,要求在两个小时内完成两道编程的题目。其中一道题目就是让编程解决“八皇后问题”。现在想起来还是挺有意思,就打算用 C# 再实现一次 :)

八皇后问题的大致意思是这样的:在一个 8*8 的矩形格子中排放 8 个皇后,要满足的条件包括:任意两个皇后都不能在同一行、同一列,也不能在同一条对角线(斜率等于1或-1)。

在考试的时候,我是用递归的方法解决的。现在想一想,还是用递归比较方便。但是需要注意的是,递归有个很大的毛病,就是递归的规模不太好控制,而且在递归很深的程序中,要调试也是一个很伤脑筋的问题。在有的公司,递归就是基本上禁止的。不过这里我就不去考虑非递归的解决方案了,反正是娱乐娱乐,何必自找麻烦呢:)

在使用递归解决此问题的时候,我采用的方法大致是这样:

  • 将一个皇后向下移动一个位置;
  • 如果没有成功移动(比如已经超出边界),失败;
  • 如果成功移动,则判断当前位置是否可用(和其他的皇后时候冲突)?如果冲突,则重做 1;
  • 继续给下一个皇后安排位置。
结束条件就是如果第一个皇后的所有位置都尝试完毕仍然没有可用的解决方案或者最后一个皇后已经安排完毕。

代码如下:

 1// AppEntry.cs
 2using System;
 3
 4namespace Chenglin
 5{
 6  class AppEntry
 7  {
 8    static void Main(string[] args)
 9    {
10      int queenNumber = 8;    
11      QueenRowCollection q = new QueenRowCollection(queenNumber);
12      
13      bool flag;
14      DateTime timeStarted = DateTime.Now;
15      flag = q.PositionQueens();
16      TimeSpan ts = DateTime.Now.Subtract( timeStarted );
17      
18      
19      if( flag ) {
20        Console.WriteLine( q.ToString() );
21      }

22      else {
23        Console.WriteLine( "Failed" );
24      }

25      
26      Console.WriteLine( "{0} seconds has been elapsed.", ts.TotalSeconds );
27    }

28  }

29}
 1// QueenRowCollection.cs
 2using System;
 3using System.Text;
 4
 5namespace Chenglin
 6{
 7  public class QueenRowCollection
 8  {
 9
10    public QueenRowCollection( int numberOfQueens ){
11      this.numberOfQueens = numberOfQueens;
12      this.rows = new QueenRow[ numberOfQueens ];
13
14      forint i=0;i<numberOfQueens;i++ ){
15        rows[i] = new QueenRow( numberOfQueens );
16      }

17    }

18
19    public bool PositionQueens()
20    {
21      return PositionQueen( 0 );
22    }

23
24    private bool PositionQueen( int row )
25    {
26      if( row>=this.numberOfQueens ) {
27        return true;
28      }

29
30      QueenRow q = rows[row];
31      while( q.MoveNext() )
32      {
33        if( PositionAvailable( row, q.CurrentPosition ) ) {
34          // An available position has been found for the current queen,
35          // and try to find a proper position for the next queen.
36          //
37          // If no available position can be found for the next queen,
38          // the current queen should move to the next position and try again.
39          //
40          if( PositionQueen( row+1 ) )
41          {
42            // Both the current queen and the next queen
43            // have found available positions.
44            //
45            return true;
46          }

47        }

48      }

49
50      // No position is available for the current queen,
51      //
52      return false;
53    }

54
55    private bool PositionAvailable( int row, int column ){
56      forint i=row-1; i>=0; i-- )
57      {
58        if( rows[i].PositionOccupied( column ) )
59          return false;
60
61        if( rows[i].PositionOccupied( column-(i-row) ) )
62          return false;
63
64        if( rows[i].PositionOccupied( column+(i-row) ) )
65          return false;
66      }

67
68      return true;
69    }

70
71    public override string ToString()
72    {
73      StringBuilder s = new StringBuilder();
74
75      foreach( QueenRow q in rows ){
76        s.AppendFormat( "{0}{1}", q, Environment.NewLine );
77      }

78
79      return s.ToString();
80    }

81
82    private int numberOfQueens;
83    private QueenRow [] rows;
84  }

85}
 1// QueenRow.cs
 2using System;
 3using System.Text;
 4
 5namespace Chenglin
 6{
 7  public class QueenRow
 8  {
 9    public QueenRow( int numberOfPositions )
10    {
11      this.numberOfPositions = numberOfPositions;
12      this.currentPosition = -1;
13      this.columns = new bool[ numberOfPositions ];
14    }

15    
16    public bool MoveNext(){
17      if( currentPosition>=0 && currentPosition<this.numberOfPositions ){
18        columns[currentPosition] = false;
19      }

20      
21      if( currentPosition<this.numberOfPositions-1){
22        currentPosition ++;
23        columns[currentPosition] = true;
24        return true;
25      }

26      else {
27        currentPosition = -1;
28        return false;
29      }

30    }

31    
32    public bool PositionOccupied( int column ){
33      if( column<0 || column>=numberOfPositions ){
34        return false;
35      }

36      
37      return columns[column];
38    }

39    
40    public override string ToString()
41    {
42      StringBuilder s = new StringBuilder();
43      
44      foreachbool b in columns ){
45        s.AppendFormat( "{0} ", (b ? "*" : "-") );
46      }

47      
48      return s.ToString();
49    }

50    
51    public int CurrentPosition
52    {
53      get return currentPosition; }
54    }

55    
56    private int currentPosition;
57    private int numberOfPositions;
58    private bool [] columns;
59  }

60}


程序运行的时候,当皇后个数增加的时候,运行的时间也会急剧增加!下面这副图表示了皇后个数与运行时间的大致关系:

posted on 2005-06-19 17:26  Lin  阅读(5799)  评论(16编辑  收藏  举报