介绍

链接:7×7 Skyscrapers

C#答案(原因:懒,但是完全可以转成C++):bajdcc/learnstl

题目(机翻):

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

  • 摩天大楼的高度在1到7之间

  • 一行或一列中的所有摩天大楼楼层数量各不相同
  • 你只知道从外面的一行或一列中看到的摩天大楼的数量
  • 高层摩天大楼阻挡了后面的下层摩天大楼,导致你看不到后面的大楼了

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

举个例子,6x6的:

6x6 摩天大楼 例

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

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

虚拟城市

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

规则3和4的说明

要求

输入:int[]

输入的数组下标

输出: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备份。

【Codewars】7×7 摩天大楼的更多相关文章

  1. [CodeWars][JS]实现链式加法

    在知乎上看到这样一个问题:http://www.zhihu.com/question/31805304; 简单地说就是实现这样一个add函数: add(x1)(x2)(x3)...(xn) == x1 ...

  2. codewars 随手记

    1.ES6数组遍历语法糖=> 在C#Linq里曾经用过,因此也不是很陌生. var range = Array.apply(null, Array(x)).map((_, i) => ++ ...

  3. window 10 用composer安装 基于 Laravel 5.3 的 Coaster CMS Curl错误77解决

    安装教程来自 http://laravelacademy.org/post/6547.html 1.系统环境windows 10 nodejs3.9.2 composer1.2.4(国内镜像) Cmd ...

  4. [stm32] 一个简单的stm32vet6驱动的天马4线SPI-1.77寸LCD彩屏DEMO

    书接上文<1.一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO> 我们发现用16MHz晶振的nRF51822驱动1.77寸的spi速度达不到要求 本节主要采用7 ...

  5. [nRF51822] 1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO

    最近用nRF51822写了个天马4线SPI的1.77寸LCD彩屏驱动,效果如下: 屏幕的规格资料为:http://pan.baidu.com/s/1gdfkr5L 屏幕的驱动资料为:http://pa ...

  6. 【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)

    本题是一道微软面试题,看起来复杂,解出来会发现其实是一个很简单的递归问题,但是这道题的递归思路是很值得我们反复推敲的. 原题为hihocoder第77周的题目. 描述 Koch Snowflake i ...

  7. NYOJ题目77开灯问题

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsUAAAHXCAIAAADbX7BCAAAgAElEQVR4nO3dvVLrSMAm4L0Jci6E2B

  8. LeetCode39/40/22/77/17/401/78/51/46/47/79 11道回溯题(Backtracking)

    LeetCode 39 class Solution { public: void dfs(int dep, int maxDep, vector<int>& cand, int ...

  9. Scala 深入浅出实战经典 第77讲:模式匹配下的提取器动手构造实战

    王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...

随机推荐

  1. 引入css的几种方式

      使用CSS样式的几种方式 CreateTime--2017年10月11日16:45:26 Author:Marydon a.外部样式 a1.链接式(推荐使用) <link href=&quo ...

  2. 【WebKit内核 CEF3 】 第一篇:下载分支代码并本地编译

    关于CEF  Chromium Embedded Framework 简单说就是  WebKit内核的 对外绑定. 当前主流浏览器内核 一.Trident内核代表产品Internet Explorer ...

  3. 【环境配置】配置ndk

    1. 背景 Android平台从诞生起,就已经支持C.C++开发. 众所周知,Android的SDK基于Java实现.这意味着基于Android SDK进行开发的第三方应用都必须使用Java语言.但这 ...

  4. iOS打包framework - Swift完整项目打包Framework,嵌入OC项目使用

    场景说明: -之前做的App,使用Swift框架语言,混合编程,内含少部分OC代码. -需要App整体功能打包成静态库,完整移植到另一个App使用,该App使用OC. -所以涉及到一个语言互转的处理, ...

  5. java多线程(五)之总结(转)

    引 如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个 ...

  6. js出现Syntax error on token "catch", Identifier expected

    本文转自:http://blog.csdn.net/u011159417/article/details/73916676 项目中需要使用jQuery,因此下载了jQuery的js包jquery-3. ...

  7. HttpClient中的Timout

    connection timeout和SoTimeout A connection timeout occurs only upon starting the TCP connection. This ...

  8. 【LeetCode】27. Remove Element (2 solutions)

    Remove Element Given an array and a value, remove all instances of that value in place and return th ...

  9. Java虚拟机学习 - 垃圾收集算法(3)

    跟踪收集器       跟踪收集器采用的为集中式的管理方式,全局记录对象之间的引用状态,执行时从一些列GC  Roots的对象做为起点,从这些节点向下开始进行搜索所有的引用链,当一个对象到GC  Ro ...

  10. Python rindex() 方法

    描述 Python rindex() 方法返回子字符串最后一次出现在字符串中的索引位置,该方法与rfind() 方法一样,只不过如果子字符串不在字符串中会报一个异常. 语法 rindex() 方法语法 ...