八皇后及任意多皇后问题解法之递归解法

基本原理

    递归解法的基本原理是把一个大问题拆分成几个类似的小问题,小问题继续拆解成更小的问题,直到不能拆解的单元问题为止,再把所有单元问题的解汇集成问题的全部解。就八皇后问题而言,可以先摆第一列,共八种位置选中,每种位置选择下,剩余的八行七列中继续摆放其他皇后,即变成了八个“八行七列棋盘摆七个皇后问题”的解的集合;八行七列的棋盘里面,摆第二列,剩余八行六列的棋盘,以此类推,直到最后一列摆上皇后。同样的,不仅八皇后,任意多个皇后的摆放问题都可以用这种方法求解。

代码实现

本功能采用c#来实现

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Windows.Forms; 
namespace EightQueens
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        
        private void Btn_Click(object sender, EventArgs e)//控件事件
        {
            const string tips = "请在皇后数量处输入大于0的整数";
            try
            {
                var queensNum = Convert.ToInt16(Text_QueensNum.Text);
                if (queensNum > 0)
                {
                    var results = EightQueens(queensNum, new List<int>());
                    text_ArrangeNum.Text = results.Count.ToString();
                }
                else
                {
                    MessageBox.Show(tips);
                }
            }
            catch
            {
                MessageBox.Show(tips);
            }
        }

        private static List<List<int>> EightQueens(int num, ICollection<int> selectedLocation)//递归方法,num为皇后总数,selectedLocation为前面已经选定的位置
        {
            var results = new List<List<int>>();
            if (num == 1)//皇后数为0时,一个格子,布置一个皇后
            {
                results.Add(new List<int> { 1 });
            }
            else if(num >3)//皇后数超过3时,递归
            {
                for (var i = 0; i < num; i++)
                {
                    if (selectedLocation.Contains(i + 1))//前面各列摆放位置已经占用的行,跳过
                    {
                        continue;
                    }
                    var selectingLocation = selectedLocation.Select(x => x).ToList();
                    selectingLocation.Add(i + 1);
                    if (CanBeArranged(selectingLocation) == false)//判断能否布置
                    {
                        selectingLocation.Remove(selectingLocation.Last());
                        continue;
                    }
                    if (selectingLocation.Count == num)//全部布置完
                    {
                        results.Add(new List<int> { i + 1 });
                        break;
                    }
                    else//布置当前这一个皇后,同时进入下一次递归
                    {
                        results.AddRange(EightQueens(num, selectingLocation).Select(x => AddElement(i + 1, x)).ToList());//当前解的集合,等于当前皇后各摆法,对应每种摆法子问题解集的集合。
                    }
                }
            }
            return results;
        }
        
        private static bool CanBeArranged(IReadOnlyList<int> resultArray)//判别能否布置,能输出true,不能输出false
        {
            for (var i = 0; i < resultArray.Count - 1; i++)
            {
                for (var j = i + 1; j < resultArray.Count; j++)
                {
                    if (resultArray[i] + i == resultArray[j] + j || resultArray[i] - i == resultArray[j] - j)
                        return false;
                }
            }
            return true;
        }
        
        private static List<T> AddElement<T>(T selectingNum, List<T> lastResult)//给List前端插入一个元素
        {
            lastResult.Insert(0, selectingNum);
            return lastResult;
        }
    }
}

界面如下图所示:
在这里插入图片描述
用户可以在界面上输入皇后数量,在摆法总数那里查看总共摆法数量。当皇后数为8时,结果如下:
在这里插入图片描述
用户也可以设断点查看具体的摆法。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值