算法 —— 回溯法 (N-皇后问题)C#

算法 —— 回溯法 (N-皇后问题)

问题描述

n−皇后问题是指将 n 个皇后放在 n×n 的国际象棋棋盘上,使得皇后不能相互攻击到,即任意两个皇后都不能处于同一行、同一列或同一斜线上。

如图,假如一个皇后在Q1位置,那么打叉的位置不能放其他皇后。
在这里插入图片描述

求解方法

i 代表行号(要放的第几个皇后)
int[] q 表示皇后存放列号

  1. 按行存放(避免同行出现)
  2. q[i] == q[j] 列相同
  3. |i-j| == |q[i]-q[j]| 行相差的绝对值和列相差的绝对值相同

代码

以下代码用了两种求解
非递归求解
递归求解

namespace ConsoleApplication1
{
    class Program
    {

        static int N = 10; //棋盘大小
        int i = 1;
        int answer = 0;//方案号
         static int[] q = new int[N + 1];//数组记录皇后位置

        /// <summary>
        /// N 皇后求解(非递归方法)
        /// </summary>
        void queen()
        {
            q = new int[N + 1];
            for (int n = 1; n <= 4; n++)//初始化皇后位置
            {
                q[n] = 0;
            }
            while (i >= 1)
            {
                q[i]++;
                while (q[i] <= N && check(i))//检查是否有冲突
                {
                    q[i]++;
                }
                if (q[i] <= N)//找到第i个存放位置,找下一个
                {
                    if (i == N)//找到最后一个了
                    {
                        answer++;
                        Debug.Write("方案" + answer + ":");
                        for (int a = 1; a <= N; a++)
                        {
                            Debug.Write(q[a] + ",");
                        }
                        Debug.WriteLine("");
                    }
                    else
                    {
                        i++;
                    }
                }
                else //没有找到
                {
                    q[i] = 0;
                    i--;
                }
            }
        }

        /// <summary>
        /// 递归求N 皇后问题
        /// </summary>
        /// <param name="i"></param>
        void queen2(int i)
        {
            for (int j = 1; j <= N; j++) //j 代表放的列号
            {
                q[i] = j;
                if (!check(i))
                {
                    if (i==N) //找到一个方案
                    {
                        answer++;
                        Debug.Write("方案" + answer + ":");
                        for (int a = 1; a <= N; a++)
                        {
                            Debug.Write(q[a] + ",");
                        }
                        Debug.WriteLine("");
                    }
                    else//找到i的位置 ,继续找i+1的位置
                    {
                        queen2(i + 1);
                    }
                }
            }

        }

        bool check(int i)
        {
            for (int j = 1; j < i; j++)
            {
                if (q[j]==q[i]||Math.Abs(i-j)==Math.Abs(q[i]-q[j]))
                {
                    return true;
                }
            }
            return false;
        }


        static void Main(string[] args)
        {
            Program p = new Program();
            //非递归求N皇后问题
            //p.queen();

            //递归求N皇后问题
            p.queen2(1);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值