(转)《编程之美》扫雷问题新解法

 原文链接:http://www.wanganran.com/blog/2010/05/minesweeper-mine-possibility.html

貌似很久没更新了,搞得google小蜘蛛们都不来了。

最近一直在想这个问题。寒假的时候看《编程之美》里的一道题:在windows里的扫雷里添加一个功能,按一个按钮可以把所有未打开的格子是雷的概率表示出来。

前几天突然想起了了这个问题,于是就开始想。。

显然深搜可以解决这个问题。把所有可以确定概率的格子(即所有已经打开的格子周围的格子)挑出来排成行,从第一个开始,只有01两种可能,同时兼顾已经打开的格子显示的周围雷数和剩余雷数,然后继续第二个格子。。直到某个格子不可能填上数,那么就回溯;或者到了最后一个格子,把每个格子的数据添加到一个记录中(一个分子数组一个分母数组,如果是1就把两个都+1,是零就只加分母),直到全部遍历完毕,两个数组中每一对数之比就是这个格子是雷的概率。耗时上,显然不会是最快的,但是人类玩的扫雷还是可以秒杀的,非人类玩的扫雷(比如1k*1k的格子数)还是留给非人类去解决吧。

但是还有没有别的方法呢?我一开始想到的是解方程组。

把所有可以确定概率的格子设成一个未知数,表示这个格子是雷的概率。然后通过打开的格子显示的周围雷数确定方程,然后解这个方程组。如果已确定的格子区域边缘都是直的(没有角),那么这个方程组显然可以解。而且和上面的那种方法所得结果相同。

但是如果已确定的格子区域是一个矩形,也就是说边缘左右已确定的格子数要小于未打开的格子数时,就会出现方程数量小于未知数数量了。

但是扫雷中会有等概率的格子。所以可以把所有在方程组中同时出现或不见的未知数当做同一个未知数,因为它们是等概率的。这样方程数量就可能等于未知数数量了。这样就可以解决类似这种的情况了:

-表示未打开的雷,数字表示已打开的雷)

---

-2-

---

但是譬如这种情况还是解决不了:

----

-11-

-11-

----

还有我们可以把一定是雷和一定不是雷的格子先挑出来,这样也能减少未知数数量。还有由于方程右边的数字只可能是整数,方程左边的未知数只可能在[0,1]之间,这样也可以确定一些一定或一定不是雷的格子。

但是上面那种情况还是解决不了。

怎么办呢。。。。。我想了快一个星期了。

其实既然这两种方法所得结果一样,可以把这两种方法结合一下。第二种方法中方程数量为i,未知数数量为j,把前j-i个未知数用第一种方法进行遍历,然后带入后再解方程组,应该也可以解出这个问题。效率上要比第一种要高一些。

但是应该还是有纯数学的解决方法的。。我没辙了,还是等待牛人来解决吧。

扩展阅读:

《编程之美》豆瓣

《编程之美》互动网

《编程之美》,IT人求职面试必读

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值