算法刷题--回溯算法与N皇后
所谓回溯算法,在笔者看来就是一种直接地思想----假设需要很多步操作才能求得最终的解,每一步操作又有很多种选择,那么我们就直接选择其中一种并依次深入下去。直到求得最终的结果,或是遇到明细的错误,回溯到上一步,换一种选择继续。就像把每种结果都遍历一遍,找到我们需要的结果。
回溯算法非常适合使用递归来求解,但与一般的递归又稍有不同。一个递归需要递归公式+递归终止条件,当然使用递归来实现的回溯算法也需要这些,只是就笔者的理解而言回溯算法还需要“回溯”这一部分。所谓回溯,就是在某一步中有多个选择的时候,选择完某一个选择后可能造成一些影响,把这些影响消除后再去选择同级的另一个选择。(笔者自己的理解,可能有不准确或是更好地描述,还望不吝赐教)
废话不多说,来看看十分著名的“N皇后”问题。题目来源与力扣(LeetCode),传送门。
51.N皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
这里稍微解释一下,N皇后问题最初来源与国际象棋的,而国际象棋的棋盘大小是8X8,因此经典版本的问题也叫“8皇后问题”。而所谓的皇后彼此之间不能相互攻击指的是:每个皇后棋子所在的行,所在的列,包括所在的对角线(两条)都没有其它棋子。
解决N皇后问题的思路是这样的,依次将棋子放到第一行,第二行...第N行。每次放置的时候都检查一下当前放棋子的位置,检查是否满足“皇后彼此之间不能相互攻击”。如果不满足要求,就在同一行内换一个位置继续尝试。如果满足要求,就到下一行继续放置棋子。贴一下笔者的代码,抛砖引玉了。(由于输出结果格式的一些问题,添加了一些不必要的代码,可以优化掉)
public class Solution {
private int count;
private IList<IList<string>> result = new List<IList<string>>();
IList<IList<string>> output = new List<IList<string>>(); public IList<IList<string>> SolveNQueens(int n)
{
count = n;
//初始化结果集合
for (int i = ; i < n; i++)
{
result.Add(new List<string>());
for (int j = ; j < n; j++)
{
result[i].Add(".");
}
}
//从第0行开始调用
calNQueens(); return output;
} private void calNQueens(int row)
{
if (row == count) //已经遍历了N行了,可以返回结果了,内层是关于格式的调整,可以优化掉的
{
List<string> temp = new List<string>(); for (int i = ; i < count; i++)
{
temp.Add(string.Join("", result[i]));
} output.Add(temp); return;
} //依次检查该列的每个位置
for (int column = ; column < count; column++)
{
if (isOk(row, column)) //放置棋子前检查是否满足要求,满足就放置棋子,并进入下一行。
{
result[row][column] = "Q";
calNQueens(row + );
}
//注意下面这一行,是笔者认为和一般的递归有些不同的地方,就是每次将“影响”消除,即“回溯”。对应到题目中去就是将刚刚放好的棋子再拿起来,避免出现一行有多个棋子的情况。
result[row][column] = ".";
} }
// 检查要放置棋子的位置是否满足条件
private bool isOk(int row, int column)
{
int leftup = column - ; //用于检查左上方的对角线
int rightup = column + ; //用于检查右上方的对角线
// 下面一段是用于检查同行内是否有重复的棋子,但其实这段逻辑是不需要的,因为在上面的调用过程中已经避免了这种情况。
// for (int i = count- ; i >= ; i--)
// {
// if (result[row][i].Equals("Q"))
// {
// return false;
// }
// } for (int i = row - ; i >= ; i--)
{
if (result[i][column].Equals("Q")) //检查同列
{
return false;
} if (leftup >= ) //检查左上方
{
if (result[i][leftup].Equals("Q"))
{
return false;
}
} if (rightup < count) //检查右上方
{
if (result[i][rightup].Equals("Q"))
{
return false;
}
} leftup--;
rightup++;
} return true;
}
}
笔者自己的思路大致是上面的样子,更详细一点的解法可以参照官方给出的解答,传送门。除了回溯的想法以外,官方的解法还有一点很有意思的优化。利用到一个公式:
对于所有的主对角线(右上到左下)有 行号 + 列号 = 常数。对于所有的次对角线(左上到右下)有 行号 - 列号 = 常数。感兴趣的小伙伴可以自己去看一哈。
关于回溯算法还有很多很多经典的问题,比如0-1背包等等,有机会再更新把。
算法刷题--回溯算法与N皇后的更多相关文章
- C#LeetCode刷题-回溯算法
回溯算法篇 # 题名 刷题 通过率 难度 10 正则表达式匹配 18.8% 困难 17 电话号码的字母组合 43.8% 中等 22 括号生成 64.9% 中等 37 解数独 45.8% ...
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化
上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来 ...
- NOI题库分治算法刷题记录
今天晚自习机房刷题,有一道题最终WA掉两组,极其不爽,晚上回家补完作业欣然搞定它,特意来写篇博文来记录下 (最想吐槽的是这个叫做分治的分类,里面的题目真的需要分治吗...) 先来说下分治法 分治法的设 ...
- 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案
八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例.该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同 ...
- leetcode 算法刷题(一)
今天开始刷Leetcode上面的算法题.我会更新我刷题过程中提交的代码(成功和不成功的都有)和比较好的解法 第二题 Add Two Numbers 题目的意思:输入两个链表,这两个链表都是倒序的数字, ...
- C#LeetCode刷题-贪心算法
贪心算法篇 # 题名 刷题 通过率 难度 44 通配符匹配 17.8% 困难 45 跳跃游戏 II 25.5% 困难 55 跳跃游戏 30.6% 中等 122 买卖股票的最佳时机 II C ...
- C#LeetCode刷题-分治算法
分治算法篇 # 题名 刷题 通过率 难度 4 两个排序数组的中位数 C#LeetCode刷题之#4-两个排序数组的中位数(Median of Two Sorted Arrays)-该题未达最优解 30 ...
- leetcode算法刷题(三)
今天在刷了几道简单的动态规划后,又看了看string方面的题 第五题 Longest Palindromic Substring 题目的意思:求一个字符串的最长回文子串 分析:开始,我的想法是,现在字 ...
- leetcode算法刷题(四)——动态规划(二)
又到了晚上,动态规划,开刷! 第121题 Best Time to Buy and Sell Stock 题目的意思:给予一个数组price,表示特定股票在某天的股价,里面第i个数表示第i天的价格.只 ...
随机推荐
- AntDesign(React)学习-7 Menu添加事件
今天花了大半天时间从老家回到工作地,路上因为肺炎封堵挺厉害,希望国家挺过这个难关,要不大家都失业可就惨了,上一篇做了一个展示数据的demo,这一篇研究antd Menu item点击事件 1.还是先看 ...
- <if test="type == '0' ">没有进去这个判断的问题
在MyBatis的mapp文件中的if判断中是这样写的 <if test="type == '0' "> and so1.id = #{unitcode} </i ...
- Windwos查看本地局域网内所有的ip方法
Windows平台ping测试局域网所有在用IP .打开cmd命令窗口 .输入命令:,,) DO ping -w -n .%i //这个是自己局域网的ip地址前三位 查看自己ip信息的命令是ipcon ...
- 计蒜客 - A1633.蒜头君的数轴
我感觉出的很好的一道题,首先不难想到(其实我刚开始没想到),加点的个数就是找已有点两两形成区间的gcd,那么问题就出在了复杂度上,每次循环哪个区间不要复杂度过高,所以运用正反两次前缀和(?好像不能这么 ...
- (转)数据库分片Shard操作
2.1.1什么是数据切分 "Shard" 这个词英文的意思是"碎片",而作为数据库相关的技术用语,似乎最早见于大型多人在线角色扮演游戏中."Shard ...
- Python_初识面向对象
楔子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏,你就思考呀,人狗作战,那至少需要2个角色,一个是人, 一个是狗,且人和狗都有不同的技能,比如人拿棍打狗, 狗 ...
- Django路由层、视图层
一.路由匹配: 第一个参数是正则表达式,匹配规则按照从上往下一次匹配,匹配到一个后立即停止 urlpatterns = [ url(r'^admin/', admin.site.urls), url( ...
- 普及C组第三题(8.12)
2304. 光芒 (File IO): input:light.in output:light.out 时间限制: 1000 ms 空间限制: 题目: 输入: 输出: 样例输入 5 1 1 0 1 ...
- mybatis(六):设计模式 - 单例模式
- 查看ie版本
window10系统还好说,一般都是IE11版本,其他系统或服务器看=查看ie版本就很烦 方法一:按组合键 ALT+H 打开“帮助”,再按 A 选择“关于Internet Explorer” 方法二 ...