浅谈八皇后问题

来源:互联网 发布:初识动画软件教学设计 编辑:程序博客网 时间:2024/04/27 04:33

写这篇文章,是由于最近看到一篇帖子,要计算800个皇后。记得当初做八皇后问题的时候,要用一个二维矩阵来存棋盘状态,算法用的是比较直观的穷举,但是考虑要存一个800*800的棋盘状态,那么首先在资源上就处于劣势,因此在原先的算法进行修改,从而减少空间的使用。

 

简述一下八皇后问题,就是在8*8的棋盘上放置八个皇后,使得各个皇后之间不能相互吃掉,每个皇后可以吃掉横、竖、斜线这四条线内的任何子,这里的斜线是45度斜线,也就是说以皇后所在的点为中心画米字。N皇后的问题以此类推。

 

大致算法如下。

    public class clsEightQueen

    {

        private int[] QueenVisited;

        private int[] QueenIndex;

        private bool bComputed;

        public readonly uint QUEEN_NUM;

 

        /// <summary>

        /// Default constructor with 8-queen

        /// </summary>

        public clsEightQueen():this( 8 )

        {

        }

 

        /// <summary>

        /// Constructor with specific queen number

        /// </summary>

        /// <param name="QueenNum"></param>

        public clsEightQueen( uint QueenNum )

        {

            QUEEN_NUM = QueenNum;

            bComputed = false;

 

            QueenVisited = new int[QUEEN_NUM];

            QueenIndex = new int[QUEEN_NUM];

        }

       

        public int this[uint Index]

        {

            get

            {

                if( Index < QUEEN_NUM )

                    return QueenIndex[Index];

                else

                    throw new Exception( "Invalid index!" );

            }

        }

 

        private void InitArray()

        {

            // Init array

            for( int i = 0; i < QUEEN_NUM; i++ )

            {

                QueenVisited[i] = 0;

                QueenIndex[i] = -1;

            }

        }

 

        /// <summary>

        /// Compute the visited list under specific queen index

        /// </summary>

        /// <param name="CurQueenIndex"></param>

        private void ComputeVisitedIndex( ref int CurQueenIndex )

        {

            // Reset visited list

            for( int i = 0; i < QUEEN_NUM; i++ )

                QueenVisited[i] = 0;

           

            // Compute the visited list using previous queen value

            for( int i = 0; i < CurQueenIndex; i++ )

            {

                QueenVisited[QueenIndex[i]]++;

                if( QueenIndex[i] + CurQueenIndex - i < QUEEN_NUM )

                    QueenVisited[QueenIndex[i] + CurQueenIndex - i]++;

                if( QueenIndex[i] - ( CurQueenIndex - i ) >= 0 )

                    QueenVisited[QueenIndex[i] - ( CurQueenIndex - i )]++;

            }

        }

 

        /// <summary>

        /// Set queen index

        /// </summary>

        /// <param name="CurQueenIndex"></param>

        /// <returns></returns>

        private bool SetQueenIndex( ref int CurQueenIndex )

        {

            int i = 0;

            for( ; i < QUEEN_NUM; i++ )

                if( QueenVisited[i] == 0 )

                    break;

 

            if( i < QUEEN_NUM )

            {

                QueenIndex[ CurQueenIndex ] = i;

                return true;

            }

            else

                return false;

        }

 

        /// <summary>

        /// Reset queen index

        /// </summary>

        /// <param name="CurQueenIndex"></param>

        /// <returns></returns>

        private bool SetNextQueenIndex( ref int CurQueenIndex )

        {

            // Roll back to previous data

            int i = QueenIndex[CurQueenIndex];

            i++;//Goto next index

            for( ; i < QUEEN_NUM; i++ )

                if( QueenVisited[i] == 0 )

                    break;

 

            if( i < QUEEN_NUM )

            {

                QueenIndex[ CurQueenIndex ] = i;

                CurQueenIndex++;

                return true;

            }

            else

                return false;

 

        }

 

        /// <summary>

        /// Compute the queen index list

        /// </summary>

        /// <returns></returns>

        public bool Compute()

        {

            int nCurQueenIndex = 0;

            bComputed = false;

            InitArray();

 

            while( nCurQueenIndex < QUEEN_NUM && nCurQueenIndex >= 0 )

            {

                ComputeVisitedIndex( ref nCurQueenIndex );

 

                if( SetQueenIndex( ref nCurQueenIndex ) )

                    nCurQueenIndex++;

                else

                {

                    //Roll back

                    do

                    {

                        nCurQueenIndex--;

                        ComputeVisitedIndex( ref nCurQueenIndex );

                    }while( !SetNextQueenIndex( ref nCurQueenIndex ) && nCurQueenIndex >= 0 );

               

                }

            }

 

            bComputed = ( nCurQueenIndex == QUEEN_NUM );

            return bComputed;

        }

 

    }

 

调用代码如下:

    clsEightQueen myEightQueen = new clsEightQueen();

    if( myEightQueen.Compute() )

    {

        for( uint i = 0; i < myEightQueen.QUEEN_NUM; i++ )

            Debug.WriteLine( string.Format( "{0}:{1}", i, myEightQueen[i] ) );

    }

 

以上代码在算40个皇后以上问题的时候,速度就很慢了。因此有些地方还是需要再考虑一下,看看是否有更好的算法。除此外,以上是使用单线程来解的,那么如何用多线程来解也是值得琢磨的。

原创粉丝点击