C# 用回溯递归解决“八皇后”问题

回溯法求解N皇后问题 本文介绍了回溯法及其在解决N皇后问题中的应用。回溯法是一种通过试探性搜索解决问题的算法,核心思想是“尝试-回退”,通过系统性搜索、剪枝优化和递归实现来高效穷举所有可能解。N皇后问题要求在n*n棋盘上放置n个皇后,使得它们互不攻击。文章详细分析了问题的解题思路,提出了剪枝条件函数,并设计了递归和非递归两种算法来实现回溯法。递归法通过递归调用逐行放置皇后,而非递归法则通过迭代实现。总结指出,回溯法通过智能穷举和剪枝优化,在解决组合问题时能显著减少无效搜索,适用于N皇后、数独、图着色等场景,是解决NP难问题的重要 阅读详情

C# 用回溯递归解决“八皇后”问题

  在很早以前,我曾经用C++写过一篇使用回溯法来生成随机数独的博客。这一次,考虑到这是一系列关于C#的博客,所以利用C#的一些特点,来解决著名的“八皇后”问题。

  一、问题概述

  问题概述搬自百度百科。八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8X8格的国际象棋棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。

  二、算法分析

  在迭代过程中,不停进行尝试,如果不行则退回来,换一条路走,这就是“回溯法”的基本思想。

  在本例中,基本算法如下:先遍历棋盘的每一行,在每一行的第一个位置放一个皇后,接下来遍历每一列,寻找下一个皇后的位置;一旦找到合适的位置,则把下一个皇后放上去;然后再寻找其下一列放皇后的位置。如果某一列不存在可以放皇后的位置(也就是“无解”的情况),则将前一步的皇后拿掉,回到前一步寻找下一个放皇后的位置。

  例如,对于以下的情况,我们无法在F列再放入一个皇后,问题“无解”,此时我们就要将E4的皇后拿走,从E5、E6、E7、E8来遍历可以放皇后的位置。拿走E4皇后的这个行为就叫做“回溯”——我们试过了不行,所以就返回换一个条件重新试。

  递归是不断调用自身的过程。其流程图大致如下所示:

  三、面向对象的思维设计

  既然是用C#来实现算法,那么就要用到面向对象的思维,而不是C语言中面向过程的思维。在本例中,我们可以看成,我们在“棋盘”上放“皇后”,可以将棋盘和皇后设计为类。棋盘的作用是,用回溯法往自身上面放“皇后”对象,皇后的作用是,记录自身所在的棋盘位置,以及判断是否与其它皇后相冲突。

  以下是Queen类(Queen.cs)的源代码:

using System;

namespace EightQueen
{
    public class Queen
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Queen(int _X, int _Y)
        {
            X = _X;
            Y = _Y;
        }

        public bool HasCollision(Queen otherQueen)
        {
            return (
                X == otherQueen.X ||
                Y == otherQueen.Y ||
                Math.Abs(X - otherQueen.X) == Math.Abs(Y - otherQueen.Y)
                );
        }

        public static bool HasCollision(Queen queen1, Queen queen2)
        {
            return (
               queen1.X == queen2.X ||
               queen1.Y == queen2.Y ||
               Math.Abs(queen1.X - queen2.X) == Math.Abs(queen1.Y - queen2.Y)
               );
        }

        public override string ToString()
        {
            return String.Format("X: {0}, Y: {1}", X, Y);
        }
    }
}
  我们可以用Queen.HasCollision来判断两个Queen类是否相冲突(是否在相同横、竖或斜线上),判断方法十分简单,如果两个皇后的X坐标相同,或者Y坐标相同,或者两个皇后的X坐标之差的绝对值与Y坐标之差的绝对值相同,则说明它们是相冲突的。

  接下来是棋盘类,它用于存放皇后。以下是棋盘类Checkerboard.cs的源代码:

using System.Collections.Generic;
using System.Text;

namespace EightQueen
{
    public class Checkerboard
    {
        public List<Queen> Queens;
        public List<int[,]> Results;
        private int Size;
        
        public Checkerboard(int size)
        {
            Size = size;
            Results = new List<int[,]>();
        }

        public int[][,] SettleQueen()
        {
            Results = new List<int[,]>();
            SettleNext(new List<Queen>(Size), 0);
            return Results.ToArray ();
        }

        private bool SettleNext(List<Queen> queens, int x)
        {
            //按照行来遍历
            for (int _x = x; _x < Size; _x++)
            {
                bool hasSettled = false;
                //按照列来遍历
                for (int _y = 0; _y < Size; _y++)
                {
                    Queen q = new Queen(_x, _y);
                    if (queens.Count == 0)
                    {
                        // 一定可以放一个皇后
                        hasSettled = true;
                        queens.Add(q);
                        hasSettled = SettleNext(queens, x + 1);
                    }
                    else
                    {
                        bool hasCollision = false;
                        foreach (var queen in queens)
                        {
                            if (queen.HasCollision (q))
                            {
                                //只要包含一个皇后冲突,则将hasCollision标记为true
                                hasCollision = true;
                                break;
                            }
                        }
                        if (!hasCollision)
                        {
                            hasSettled = true;
                            queens.Add(q);
                            hasSettled = SettleNext(queens, x + 1);
                        }
                    }
                }
                if (!hasSettled)
                {
                    //遍历完一列后,如果没有合适的摆放位置,则回溯
                    //此时有两种情况:如果queens集合成语数量大于0,说明它可以进行回溯;如果等于0,说明它已经将所有的情况遍历完成,此时应该终止递归。
                    if (queens.Count > 0)
                    {
                        queens.RemoveAt(queens.Count - 1);
                        return false;
                    }
                    return true;
                }
            }

            if (queens.Count == Size)
            {
                Results.Add(ToResultMap(queens));
                //得到一种解后,回溯,寻求下一个解
                //遍历完一列后,如果没有合适的摆放位置,则回溯
                queens.RemoveAt(queens.Count - 1);
                return false;
            }
            return true;
        }

        private int[,] ToResultMap(IEnumerable<Queen> queens)
        {
            int[,] result = new int[Size, Size];
            //把所有数组中的数字赋予初值0
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    result[i, j] = 0;
                }
            }
            //将皇后的位置标记为1
            foreach (var queen in queens)
            {
                result[queen.Y, queen.X] = 1;
            }

            return result;
        }

        public static string ResultMapToString(int[,] resultMap)
        {
            StringBuilder sb = new StringBuilder((int)(resultMap.GetLongLength(0) * resultMap.GetLongLength(1)));
            for (int i = 0; i < resultMap.GetLongLength (0); i++)
            {
                for (int j = 0; j < resultMap.GetLongLength(1); j++)
                {
                    sb.Append(resultMap[i, j] == 0 ? "□" : "■");
                }
                sb.AppendLine();
            }

            return sb.ToString();
        }
    }
}
  棋盘类在实例化的时候可以接入一个Size参数,表明是棋盘的大小。在设计时,为了解决这一类问题,不应当把棋盘的大小限定为8x8。Queens保存的是某一个解中的Queen对象组,通过ToResultMap方法,传入Queens,可以得到一个矩形数组int[,],元素总数是Size * Size。数组表示的是一个棋盘,如果某位置没有皇后,则为0,某位置放了皇后,则为1。如果你觉得这样不够直观,可以用ResultMapToString将这个矩形数组以文本的形式返回。

  下面是程序的入口Program.cs:

using System;

namespace EightQueen
{
    class Program
    {
        static void Main(string[] args)
        {
            Checkerboard checkerboard = new Checkerboard(8);
            int[][,] results = checkerboard.SettleQueen();
            foreach (int[,] result in results)
            {
                Console.WriteLine(Checkerboard.ResultMapToString(result));
            }
            Console.WriteLine("共{0}组解。", results.Length);
            Console.ReadKey(true);
        }
    }
}

  首先实例化一个棋盘Checkerboard,大小为8*8。通过调用Checkerboard.SettleQueen来得到所有解,通过遍历所有解,调用Checkerboard.ResultMapToString方法将所有解输出,最后输出解的总数。

  在此我们已经看出面向对象编程的好处了。整个程序一目了然,非常简单、清晰。

  事实上,只要棋盘的大小≥4,就存在解,大家可以去试一试。

用回溯法解决八皇后问题的思路,并求出17皇后解的数量(c#,c++,python表示) 1.解决思路借用网上一张图,中间那个红点表示的就是皇后,这图的意思也就是一个皇后的影响范围为这这个皇后所在的那一列,那一行,对角线以及次对角线。其它的皇后不能在它的影响范围里否则会冲突。八皇后也就是在一个8x8的棋盘上后置8个皇后,皇后的数量与棋盘的行列数一样。这是基础,再来说说回溯法,回溯法最重要的思想就是当前这一步走不通,我们就掉头返回上一步找其他方案。这相对于枚举法列出所有可能再逐个进行排除... 阅读详情

相关推荐

C#回溯法8皇后问题-实验报告+程序

使用C#编写回溯法解决8皇后问题的实验报告和程序 有图形界面,可以查看任意一种解法

用C#语言实现八皇后问题

C#实现八皇后问题

Paul的博客 3754

金蝶云苍穹-插件开发(一)加载数据

此系列博客是进行金蝶云苍穹开发时的插件开发的教程,一是在明年要是还要参加软件杯金蝶A6赛题的话,可以看此系列教程的博客来进行复习,同时如果要是我实验室的学弟学妹要参加的话,我这个系列的博客可以给他们提供学习参考,因为插件开发学习的路上很艰难,我学习的时候,能参照的讲解少,要花费大量工夫去猜测去调试才能学会那些语法。在插件开发上,希望我这个系列的博客能帮助到别人。这个系列的博客只专门讲解插件开发,基本的那些金蝶云苍穹的知识点在这里不多作讲解。

二狗mao的博客 3588

八皇后问题 C#版本算法 回溯法

本文中的代码在文章最后提供下载链接。 关于八皇后的问题,自己百度。回溯法的概念也可以自己维基百科中查看。 回溯法无非就是遍历解空间,如果合适的话就继续,不合适的话就放弃当前节点。可以采用递归实现。八皇后问题的经典算法就是采用回溯法。网上也有许多版本的解法,但是C#版本的似乎很少。笔者在此奉献上。 此处八皇后的算法的伪代码如下: 在第row行放置皇后(row) { for 第row行的格...

weixin_33961829的博客 237

Verilog实战:手把手教你实现四路组相联Cache(附完整代码解析)

本文提供了一份详细的Verilog实战指南,手把手教你实现一个四路组相联Cache。内容涵盖从设计规格、核心存储阵列、LRU替换策略到状态机设计的完整流程,并附有代码解析与优化技巧,旨在帮助硬件设计者掌握Cache控制器的RTL实现与调试方法。

pp12345的博客 517

UE4虚拟现实实习总结---蓝图中的常用交互事件|人物行走|物体移动|动态触发|材质改变

这周是ue4实习周,老师给我们的任务就是基于中学物理和化学实验的虚拟实验室,要有交互事件,后期可以链接vr手柄进行操作。 但是实习开始老师影都没了,全靠自己学习。感觉自己学习了不少东西,这里就来总结一下!顺便感叹一下,ue4好玩又强大! 以下主要介绍蓝图中的几种交互事件1.新建游戏角色并且进行角色行走旋转,2.如何控制物体移动旋转,3.如何控制物体材质动态变化 大家可以举一反三,作出更好的作品 1.新建游戏角色并且进行角色行走旋转 步骤 在刚刚新建的文件夹中鼠标右击新建蓝图类,然后分别创建以下:chara

weixin_43902063的博客 6123

回溯法——八皇后问题

回溯法的基本做法是搜索,或是一种组织得井井有条的,能避免不必要搜索的穷举式搜索法。这种方法适用于解一些组合数相当大的问题。 回溯法在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;否则,进入该子树,继续按深度优先策略搜索。 回溯法指导思想——走不通,就...

weixin_34396103的博客 313

别再死磕Excel了!用Vensim PLE免费版,30分钟搞定你的第一个系统动力学模型

本文介绍如何使用Vensim PLE免费版在30分钟内构建第一个系统动力学模型,无需编程或数学基础。通过个人储蓄增长案例,详细讲解因果回路图绘制、存量流量图创建及方程编写,帮助读者掌握动态系统建模与仿真技巧,适用于理财、项目管理等多种场景。

weixin_29045001的博客 329

C#写八皇后

C#写八皇后 引言 刚开始接触到C#是因为想要用Unity自己做游戏 ,把脑海里的创意落到屏幕前。 而所有的Unity教程里都是从C#起步,所以就想好好学门C# 任务 这是老师布置的作业: 2.3 在8X8格的国际象棋棋盘上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上。请输出尽可能多的摆法。 环境 Visual stdio 2019 思路 为了对棋盘的布局有个清晰地了解,我们可以这样想:任意两个皇后不能在同一行,那么就说明一行放一个皇后,那么只要找到每行的皇后分别放在

hanhandeguajian的博客 527

引文:当SVM转角遇上Copy-on-Write (COW)

本文分析了Linux内核中fork系统调用的Copy-on-Write(COW)机制实现原理。重点阐述了fork时父子进程共享物理页面、标记页表项为只读并在写操作时触发COW的流程,以及在SVM环境中通过MMU Notifier机制保持CPU和GPU页表同步的解决方案。文章详细描述了COW的三个阶段:初始共享、写入触发和页面复制,并说明了MMU Notifier的回调注册和处理流程,确保异构计算环境下内存一致性。

图形/计算GPU的驱动与虚拟化技术分享园地 2673

【踩坑记录】colmap中的相机位姿的坐标系定义及其可视化结果的隐含转换

1 坐标系定义及转换   首先介绍一下世界坐标系和相机坐标系之间的转换,它们之间是存在一个转换关系的。现假设空间中一点X,它在相机坐标系下的坐标是Xcamera,在世界坐标系下的坐标是Xworld。假设它通过R和t实现从相机坐标系到世界坐标系之间的转换: Xworld = RXcamera + t   那么,由上式,我们可以推得从世界坐标系向相机坐标系的转换关系(RT=R-1,所以通常直接使用RT即可): Xcamera = RTXworld - RTt   所以,两个坐标系之间的转换,需要看其具体

zeeq的博客 2万+

C#八皇后算法:回溯法 vs 列优先法 vs 行优先法 vs 对角线优先法

该方法首先选择一个空的棋盘,然后从左上角开始,尝试将皇后放置在对角线上。否则,尝试下一个对角线。当找到一个有效的对角线时,将皇后放置在该对角线的当前列。与列优先法类似,但不同之处在于,该方法从第一列开始,尝试将皇后放置在每一行。当找到一个有效的行时,将皇后放置在该行的当前列。首先选择一个空的棋盘,然后从第一行开始,尝试将皇后放置在每一列。当找到一个有效的列时,将皇后放置在该列的最下方。皇后问题是一个古老而著名的问题,它实质上就是使棋盘上的8个皇后不能在同一行、同一列或同一条斜线上,共有92种方法。

wenchm的博客 1665

RLHF 家族的奇巧魔改:On Policy 与 Off Policy 路线大PK

无论是 On Policy 还是 Off Policy,RLHF 家族的“魔改”之路都充满了奇思妙想。相信随着研究的深入,RLHF 技术将会在 Alignment 领域发挥越来越重要的作用。

步子哥的博客 2083

【回溯法】八皇后问题

八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。计算机发明后,有多种计算机语言可以解决此问题。...

永生只是一场幻梦 3212

RT-Thread littefs控制GD32F4xx片内Flash

GD32F4xx RT-Thread下使用littefs 控制片内flash 调试记录

madao1234的博客 995

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

回溯法解决N皇后的问题

# 使用回溯法解决N皇后的问题 def mk_lst(size): # 生成棋盘 return [[0 for i in range(size)] for j in range(size)] def is_legal_posi(loca, size): # 判断是否合法坐标 x, y = loca[0], loca[1] size -= 1 if 0 &...

qq_32835305的博客 792

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

探索C#编程:高效解决N皇后问题的回溯算法实现

在C#中,回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化来撤销上一步或上几步的计算,以获得新的候选解。这个过程一直进行,直到找到所有解或确定无解。回溯算法常用于解决组合问题、排列问题、子集问题、棋盘问题(如八皇后问题)、图的着色问题、旅行商问题等。

学习和分享 742

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

回溯法解决“八皇后”问题

Technorati 标签: 回溯法,backtrack,八皇后,eight queens puzzle         “回溯法”和“八皇后”问题本身不再多做介绍,相信很多人都知道,尤其是学习过数据结构的人。如果还不清楚可以google或者baidu一下,亦或是找本数据结构的书看一下。         “八皇后”问题:可以简单的理解为在一个8*8的棋盘上,放8个旗子(国际象棋中称为皇后queen),要求这8个棋子中任意两个都不在同一行、列、斜线上。         “回溯法”用在这里的思路是:

大黑暗天 的专栏 2599

数据结构—八皇后问题(回溯法)

回溯法,又被称为“试探法”。解决问题时,每进行一步,都是抱着试试看的态度,如果发现当前选择并不是最好的,或者这么走下去肯定达不到目标,立刻做回退操作重新选择。这种走不通就回退再走的方法就是回溯法。 回溯VS递归 很多人认为回溯和递归是一样的,其实不然。在回溯法中可以看到有递归的身影,但是两者是有区别的。 回溯法从问题本身出发,寻找可能实现的所有情况。和穷举法的思想相近,不同在于穷举法是将所有的情况...

weixin_43869906的博客 571

用回溯法解决八皇后问题--C语言

问题描述:要求在8x8的国际象棋棋盘上放入八个皇后,使得任意两个皇后不能处于同一列,同一行,同一条斜线上。 算法思路: 1) 判断皇后之间有没有冲突,要引入四个量–row(行号,也对应于皇后的编号),column[ ](列号),slash[ ](斜线方向), bslash[ ](反斜线方向); 2) 由棋盘的布局可以发现,在斜线方向上有15条对角线,每一条穿过的各个方格有如下性质:该方格的行号加...

Leeoo_lyq的博客 1618

【递归算法】递归算法的快速入门

本文主要介绍了递归的基本概念、应用场景和原则。

baidu_33146219的博客 1万+

使用C#求解N皇后问题。

下面这个算法实现了列出所有可能放置的情况。using System; namespace Queen{        public class NQueen        {                private int m_N;   // m_N维的皇后放置问题。                private int [,] m_Houses;  // 放

diandian82的专栏 1619

C#递归使用及八皇后问题

递归简单使用(寻找路径) 题目描述 如图所示的地图,有颜色的区域代表有墙体,无法通过,现需要从a点到达b点,通过递归来查找可行路径 代码 using System; namespace MazeExample { class Program { static void Main(string[] args) { //创建一个二维数组模拟迷宫 int[,] map = new int[8, 7];

RoySummy的博客 499

回溯算法(N皇后)--C#版代码

前言: 内容: 1、回溯法基本思想: 2、N皇后问题: (1)概念: 这是来源于国际象棋的一个问题。N后问题要求在一个N x N格的棋盘上放置n个皇后,使得他们彼此不受攻击。按照国际象棋的规则,一个皇后可以攻击与之处在同一行或同一列或同一斜线上的其他任何棋子。因此,n后问题等价于要求在一个N x N格的棋盘上放置n个皇后,使得任何两个皇后不能被放在同一行或同一列或同一条斜线上。 (2)

杨楠 1829

八皇后问题的C#解答

using System; class Queen{ const int SIZE = 8;//皇后数 public static void Main() { int[] Queen = new int [SIZE];//每行皇后的位置 int y,x,i,j,d,t=0; y = 0; Queen[0] = -1; while( true ) { for (x=Queen[y]+1; x{ fo

QQMagicer的专栏 1292
上一篇: C# 继承、接口与多态
下一篇: C# Java 内部类之间的比较
Froser
博客等级 码龄17年 131粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值