【Codewars】7×7 摩天大楼

v2-b02ba5440139b21ee6a2ceba5158c0ed_1200x500

介绍

连接:7×7 Skyscrapersjava

C#答案(缘由:懒,可是彻底能够转成C++):bajdcc/learnstlgit

题目(机翻):github

在7乘7格的网格中,你只想在每一个广场上放置一个摩天大楼,只有一些线索:数组

  • 摩天大楼的高度在1到7之间
  • 一行或一列中的全部摩天大楼楼层数量各不相同
  • 你只知道从外面的一行或一列中看到的摩天大楼的数量
  • 高层摩天大楼阻挡了后面的下层摩天大楼,致使你看不到后面的大楼了

你能写一个能解决这个难题的程序吗?函数

举个例子,6x6的:测试

v2-a45496bad9d0aadfb3e2361ac5b8ad49_hd

6x6 摩天大楼 例优化

(有人说看不懂规则3和4,我就以图来讲明一下)3d

我根据上图制做了一个假城市(bajdcc/UnityTest),以下:code

v2-9a35e16413c8e62d9ec55abd6c0a5d3d_r虚拟城市blog

咱们看线索中的左侧(3,4,4):

v2-489542dd990bc52f26c035d8b8b58398_r规则3和4的说明

要求

输入:int[]

v2-587af0b069f7696a90049be18391f65c_hd

输入的数组下标

输出:int[][]

分析

花了两天思考这个系列的问题,最终固然是写出来了(光想没用)。

这个题目感受跟数独很像,我最早想的思路就是一步步推理,直到解决问题,然而,4x4大小的推理规则在6x6大小的问题中,可能须要补充一些东西或有些东西不实用了,这就麻烦了。

老实说,作数独题的时候,我不怎么用穷举法,我是对当前局面进行推理,利用排除法一步步肯定答案,但用代码实现推理就变得困难了,虽然这样作是最优的(由于根据不作多余计算)。
推理不能用,那就老老实实用穷举法吧,虽然穷举法有点low,但只要能过就行。

题目中透露了一些可供优化的信息:各行各列中数是惟一的。这就意味着复杂度从O(n^n)降低到O(n!)。这跟八皇后有点像,但又有所不一样,所以我就用回溯法作。

进一步思考

肯定用回溯作,也感受能够借鉴八皇后的思路,还不能立刻开工,有几个问题:

  1. 全排列的生成,这个嘛拿以前的代码粘贴下
  2. 回溯遍历的顺序,这个顺序大有文章

先解决全排列问题:抄了下https://github.com/bajdcc/jProlog/blob/master/src/com/bajdcc/rt/gen/array/RtNorepArray.java#L43 哈哈。

回溯的顺序应该是怎样呢?本身试喽。

先生成全排列,而后计算从左边向右看到的楼层数(假设为Sky函数,Sky:=int->int),将结果存到字典中。

会发现,当n=7时,sky(7)=1,可能性最低,都算出来后,排序。

sky(7)<sky(6)<sky(5)<sky(1)<sky(4)<sky(3)<sky(2)

展开顺序的话,我确定先找n=7的状况的,由于这时的不肯定性最低(解只有一个),至关于能够肯定一个格子的值了。

目前的思路是:找到值=7的数,就直接敲定一排解(1~7);再找值=6的数,这时答案不惟一,回溯;继续找……

这样运行程序的话,确定是耗时很长的,缘由是什么?

再想想

咱们优化程序的目标是回溯时尽能够减小回溯次数,那就必须在决定一个展开顺序:先展开不肯定性小的,再展开不肯定性较大的。

有一种状况,能够减小不肯定性:若是一排格子的两侧都有数字(都不是零),那其实能够将它们放到一块儿回溯。例: 5 | x x x x x x x | 2,这样能够极大下降可能性。事实证实这样作有一点效果。

思路有了:

  1. 将规则排好序(数大,对位匹配优先),回溯规则
  2. 保存现场,查看是否冲突,一是当前的测试值是否与该行/列冲突,二是测试值是否知足各行/列数惟一的原则
  3. 若是失败,回溯
  4. 若是成功,level+=1,再测试下一个规则
  5. 若是level==规则总数,意味着经过了全部规则,此时还不能肯定解是否正确
  6. 规则有覆盖不到的行/列,此时要将值是零的格子进行填空
  7. 填空的办法是用排除法,而后不断遍历填空,若是最后填空失败,则解不正确,若是填空成功,则解正确

注意点:

  1. 坐标系问题,方向问题
  2. 判断条件是否完备
  3. 尽可能用数组作(用list<>居然比int[]快。。)
  4. 等等细节问题

代码比较啰嗦,460行,不贴了(别人写得都很短简直了)。

https://zhuanlan.zhihu.com/p/30713476备份。

相关文章
相关标签/搜索