[回溯与约束编程] : N-皇后问题 与 填数独 等问题的通用解法

一、问题描述

在刷LeetCode的时候,有时候会遇到一些"约束条件"的问题,比如填数独:

其约束条件正如题中的1、2、3点所示,作为一道难度为hard的题目,乍一看好像没有思绪-------

在空的位置应该填什么?比如上图中第一个九宫格中3的右侧,其所在的列已经有8,所在的行已经有3,5,7,也就是说,还剩下1、2、4、6、9可以填,那么到底填多少?如果填了1,能保证后序的空格满足约束条件吗?

本人也是,一开始的时候陷入了这种“思维混沌”里,毕竟人脑是有限的,一下子很难推测到未来N步的情形,怎么办?当然是借助计算机,类比我们手动填数独的时候,按找上一段的步骤,类似一种“试错”的过程:即先假设某个解是可行的,然后存入该解,这时候系统转移到下一个状态,如果无法转移到终态,也就意味着上一步的“可能的解”是错的,所以我们需要回溯到上一步,尝试其他解。对于机器而言,这样的试错过程远比人脑计算来的快。

 

同样的,让我们看看所谓的N皇后问题

题目的约束条件是:皇后之间不能相互攻击,等价于“某个皇后所在的行、列以及对角线上不能有其他皇后存在”

这个问题相对于填数独其实简化了空间维度,我们可以按照“逐行”或者“逐列”的方式来填入皇后(这样可以先满足每一行或者每一列只有一个皇后的条件)。

比如我们按照逐行的方式来,在第一行的时候,因为先前没有填入任何一个皇后,所以在第一行的任意一列填入皇后看上去似乎都是可行的,我们不妨随机找一个位置填入。然后到了第二行,除了第一行填入位置的所在列,以及对角线的所在列,其他位置我们似乎也都可以填入一个皇后...这样,如果直到最后一行也能恰好填入皇后,说明这种分布是“正确的”;反之,如果无法填入所有的皇后,意味着我们先前的选择存在错误,因此必须逐层回溯上去,重新填入皇后。以此往复。

二、通用解法与形式

先前的部分,我们讨论了“约束条件”的两个经典问题,并且大致描述了解法。这种解法可以被归纳为“约束编程+回溯”。

所谓的约束编程也就是“条件受限”,即问题的解需要满足条件。

而回溯也就是通常而言的“递归”思路,一个问题的解可以被拆分为当前状态的解和未来状态的解,而未来状态的解是当前问题的一个子问题,或者说,未来状态的解的形式和当前状态的解形式相同。

可以被归纳为如下伪代码:

Solve(参数1,参数2,参数3...){

      for( 尝试可能的解){   

                if(不满足约束)   continue;

                填入解;

                Solve(新参数1,新参数2,新参数3)

                剔除解

        }

}

很多涉及到回溯的问题都有类似上述的"填入解"和"剔除解"这样成对的形式,目的是保证一种解尝试完之后,可以尝试新的解,如果只填入解而不剔除的话,之后尝试新的解的状态就不再是当前的初始状态了。

三、代码示例

1、填数独

2、N-皇后

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值