puzzle(1221)嵌套逻辑推理

目录

一,嵌套推理:多人零和博弈

5个囚犯抓豆子

5个海盗分金币

猴子和鳄鱼

三个枪手

二,嵌套推理:多人合作博弈

猜生日

猜自己的数

猜3个数

S先生和P先生

三个班级

无限多层嵌套推理


一,嵌套推理:多人零和博弈

5个囚犯抓豆子

问题:

5个囚犯,分别按1-5号在装有100颗绿豆的麻袋抓豆子,规定每人至少抓0颗,至多随便哪个人都可以抓完,某个人抓完之后后面的人就只能抓0个豆子。100颗豆子不必都抓完。

最后,抓得最多的人(1-5个)和抓得最少的人(1-5个)都将被处死,而且,他们之间不能交流,但在抓的时候,可以摸出剩下的豆子数。他们的原则是先求保命,能活下来一定比不能活下来要好。如果确定能活下来,再尽量去多杀人 ,如果确定不能活下来,也要去尽量多杀人。问最后的结果如何?

假设第1个人取了x个,在第1个人的心中可以这么分类:

(1)如果21<=x<=50,那么第2个人取x-1即可存活

(2)如果51<=x<=99,那么第2个人取100-x即可存活

(3)如果x=100,那么所有人都会死

(4)如果0<=x<=20,不难推出,所有人都会死(详情略)

而且,不管是哪种情况,第1个人都会死

所以,没人能存活,这个结论并不难得到。

但是关于结果,除了没人能存活之外,还可以继续讨论,这些人可能怎么取?

很多人都说最后一定是每个人都取了20个,这纯属扯淡。

既然第1个人知道必死,为什么不能一开始就取100个呢?

详细说来:

(1)如果21<=x<=99,那么第2个人会存活,这是第1个人不允许的

(2)如果x=100,这是可以的,其中只有(100,0,0,0,0)这一种情况

(3)如果x=20,那么绝对不可能有人取超过20个,但是却可能有人取少于20个

为什么会有这样的差别呢?

因为如果有人超过20的话,第1个人就存活了,但是如果有人取少于20个,还是可能所有人都死掉

具体说来,可以分2类,一类是(20,20,20,20,a),其中0<=a<=20,有21种情况

另一类是(20,b,c,d,e)其中b,c,d,e都是取19或者20,有16种情况

这2类里面有2种情况是重复的,所以一共是35种情况

(4)如果x=0,那么和上面一样,可以分为2类

一类是(0,0,0,0,a),其中0<=a<=100,有101种情况

另外一类是(0,b,c,d,e)其中b,c,d,e都是取1或者0,有16种情况

这2类里面有2种情况是重复的,所以一共是115种情况

(5)如果1<=x<=19,那么第二个人可以取x-1或x或x+1

如果第2个人取x-1,后面每个人只能取x-1或者x,有8种情况

如果第2个人取x+1,后面每个人只能取x+1或者x,有8种情况

如果第2个人取x,继续分类讨论第三个人:如果第3个人取x-1或者x+1,各有4种情况,如果第3个人取x,有7种情况,一共15种情况

对于每个x有31种情况,一共是19*31=589种情况

综上所述,一共有740种情况,即上面描述的这740种。

5个海盗分金币

问题:

经济学上有个“海盗分金”模型,是说5个海盗抢得100枚金币,他们按抽签的顺序依次提方案:首先由1号提出分配方案,然后5人表决,超过半数同意方案才被通过,否则他将被扔入大海喂鲨鱼,依此类推。海盗在自己的收益最大化的前提下乐意看到其他海盗被扔入大海喂鲨鱼,假定每个海盗都是绝顶聪明且很理智,那么第一个海盗提出怎样的分配方案才能够使自己的收益最大化?

解答:

逆推法,从后向前推,如果1至3号强盗都喂了鲨鱼,只剩4号和5号的话,5号一定投反对票让4号喂鲨鱼,以独吞全部金币。所以,4号惟有支持3号才能保命。
3号知道这一点,就会提出“100,0,0”的分配方案,对4号、5号一毛不拔而将全部金币归为已有,因为他知道4号一无所获但还是会投赞成票,再加上自己一票,他的方案即可通过。
不过,2号推知3号的方案,就会提出“98,0,1,1”的方案,即放弃3号,而给予4号和5号各一枚金币。由于该方案对于4号和5号来说比在3号分配时更为有利,他们将支持他而不希望他出局而由3号来分配。这样,2号将拿走98枚金币。
同样,2号的方案也会被1号所洞悉,1号并将提出(97,0,1,2,0)或(97,0,1,0,2)的方案,即放弃2号,而给3号一枚金币,同时给4号(或5号)2枚金币。由于1号的这一方案对于3号和4号(或5号)来说,相比2号分配时更优,他们将投1号的赞成票,再加上1号自己的票,1号的方案可获通过,97枚金币可轻松落入囊中。这无疑是1号能够获取最大收益的方案了!答案是:1号强盗分给3号1枚金币,分给4号或5号强盗2枚,自己独得97枚。

分配方案可写成(97,0,1,2,0)或(97,0,1,0,2)

如果把条件“超过半数同意方案才被通过”改成“超过半数或刚好半数同意方案才被通过”,结果又如何呢?

同样还是倒推,如果1至3号强盗都喂了鲨鱼,4号提出(100,0)可以获得最大利益。

往前倒推,3号会提出(99,0,1)让5号支持他。

往前倒推,2号会提出(99,0,1,0)让4号支持他。

往前倒推,1号会提出(98,0,1,0,1)让3号和5号支持他。

分配方案就是(98,0,1,0,1)

其实这2种情况都差不多,差别不大。

但是直觉上,我们会感觉这种场景和生活上差别很大,结果让人很诧异,这又是为什么呢?

首先,不同意的话就把人丢出去喂鲨鱼,这个肯定和日常生活不一样,但是这并不是关键,

实际上,即使去掉这个条件,结果也不会有太大差别,详情如下:

如果将原题去掉不同意的话就把人丢出去喂鲨鱼这个条件,

如果1至3号强盗都喂了鲨鱼,4号可以提出任何方案,但是只有(0,100)会通过

往前倒推,3号会提出(99,1,0)

往前倒推,2号会提出(99,0,0,1)

往前倒推,1号会提出(98,0,1,1,0)

如果把条件“超过半数同意方案才被通过”改成“超过半数或刚好半数同意方案才被通过”,再去掉不同意的话就把人丢出去喂鲨鱼这个条件,这样和没去掉这个条件其实是一样的,最后的结果还是1号会提出(98,0,1,0,1)

除掉不同意的话就把人丢出去喂鲨鱼之外,假定每个海盗都是绝顶聪明且很理智,这个虽然和现实不完全一致,但是对于这种简单的逻辑推理,还是有很多人可以想通透的,所以说,这也不是关键的区别。

结果让人很诧异的真正原因,本题和现实的关键区别,在于本题中的5个人是独立决策的,也就是说,这个博弈问题是一种纳什均衡。

虽然没有明说,但是在这种题目中,这也算是通规则了。

否则的话,如果没有这条规则,2、3、4、5号完全可以商量出对策,每个人得25,自然比同意1的方案要好得多。

但是这样的话,问题就变得复杂的多了,因为不同的人都可以私下商量对策,最后就没完没了了。

猴子和鳄鱼

孤岛上有一只猴子,孤岛周围全是海,海里有1000只鳄鱼。
假设每只鳄鱼都是理性且足够聪明的,每只鳄鱼都非常想吃猴子,但是鳄鱼吃了猴子之后,自己就会变成猴子,从而其他的鳄鱼就有可能会把它给吃了。
注意:猴子只能吃或者被吃,不存在大家分着吃一口的情况。
请问,第一只猴子会被吃掉吗?

分析:倒推十分简单

1只鳄鱼的话会吃猴子,所以2只鳄鱼不会吃,3只鳄鱼会吃。。。。。。

所以1000只鳄鱼不会吃猴子。

三个枪手

三人决定用手枪进行一次决斗。小李的命中率是30%,小黄是50%, 小林是100%。小李先开枪,小黄第二,小林最后。然后这样循环,直到他们只剩下一个人。那么他们都应该采取什么样的策略?存活率都是多少?

答案:

如果只剩下2个人,那么双方都向对方开枪,没有策略可言。

所以要问策略就是要问,如果3个人都没死,那么每个人都这么做。

首先很明显,小林的策略肯定是干掉小黄。

其次,正是知道这一点,所以小黄的策略必定是向小林开枪。

最后是小李的策略,小李如果杀了小黄,那么小李就必死了,所以很多地方出现的答案都是小李向小林开枪,实则不然。

(1)如果小李杀死了小林,那么小李的存活率是50%*(30%+30%*35%+30%*35%*35%+......)=3/13

(2)如果小李没杀死小林,那么分2种,

若小黄杀死了小林,则小李的存活率是30%+30%*35%+30%*35%*35%+......=6/13,

若小黄没杀死小林,则小李的存活率是30%,

综合2种情况,存活率是50%*6/13+50%*30%=3/13+15%

所以说,小黄杀死小林还不如没杀死小林,所以小黄的策略是谁都不杀。

下面计算存活率:

其实前面已经算过了,小李的存活率是3/13+15%=38%

小林的存活率是50%*70%=35%

所以小黄的存活率是27%

二,嵌套推理:多人合作博弈

这一类问题,基本上都是猜数问题

猜生日

小刘和小红都是张老师的学生,张老师的生日是M月N日,两人都知道张老师的生日时下列十组中的一天,张老师把M值告诉了小刘,把N值告诉了小红,然后问他们老师的生日到底是哪一天。
3月4日、3月5日、3月8日、6月4日、6月7日、9月1日、9月5日、12月1日、12月2日、12月日8
小刘说:我不知道,小红肯定也不知道。
小红说:刚才我不知道,听小刘一说我就知道了。
小刘说:哦,那我也知道了。
请根据以上对话推断出张老师的生日是哪一天?

题目来源(略改):湖南省首届逻辑推理大赛(中南大学)

分析:

首先画表

根据小刘的第一句话,可以删掉2行,变成:

根据小红的话,可以删掉1列,变成:

根据小刘的第二句话,可以得到结果是9月1日

这个题目有个特性:作为第三方的推理者,我们所知道的事实,小红和小刘全部都知道。

猜自己的数

一天教授给他们出了一个题,教授在每个人脑门上贴了一张纸条并告诉他们,每个人的纸条上都写了一个正整数,且某两个数的和等于第三个!(每个人可以看见另两个数,但看不见自己的)

教授依次每次都问一个学生,能否猜出自己的数

问第一个学生,回答不能,问第二个学生,回答不能,问第三个学生,回答不能

再问第一个,回答不能,问第二个,回答不能,问第三个,回答:我猜出来了,是144!

教授很满意的笑了。请问您能猜出另外两个人的数吗?

分析:

这个题目流传很广,很多人都已经发现,这个题目有问题,或者说,根本就无解。

很多人说答案是48,96,144,但是实际上,如果真是这样的话,第一次问到第三个同学的时候他就应该回答144

因为他知道自己不是48,否则的话,之前第二个同学就不会回答不能。

猜3个数

一个经理有三个女儿,三个女儿的年龄加起来等于13,三个女儿的年龄乘起来等于经理自己的年龄,有一个下属已知道经理的年龄,但仍不能确定经理三个女儿的年龄,这时经理说只有一个女儿的头发是黑的,然后这个下属就知道了经理三个女儿的年龄。请问三个女儿的年龄分别是多少?

分析:首先列举所有可能的情况

1*1*11=11,1*2*10=20,1*3*9=27,1*4*8=32,1*5*7=35,1*6*6=36
2*2*9=36,2*3*8=48,2*4*7=56,2*5*6=60,
3*3*7=63,3*4*6=72,3*5*5=75,4*4*5=80

然后乘积一样的只有1*6*6=36和2*2*9=36

所以三个女儿的年龄分别是2,2,9

S先生和P先生

设有两个自然数m、n,2≤m≤n≤99,A=m+n,B=m*n

S先生知道A,P先生知道B.
他们二人进行了如下的对话:
S:我知道你不知道这两个数是什么,但我也不知道.
P:现在我知道这两个数了.
S:现在我也知道这两个数了.

由上述条件及两位先生的对话,试确定m、n   

分析:

100以内的素数:2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

根据S的第一句话,A一定不是2个素数的和,而且3<A<54,否则P一开始就知道这2个数了。

所以A只能是53、51、47、41、37、35、29、27、23、17、11,而且无论A是这11个数里面的哪个,都符合S的第一句话

再根据P的话,说明B拆开成2个数的积不止1种形式,但只有1种满足2个数的和在上面 11个数里面

最后根据S的第二句话,这样的B只有1个

如果A是53,那么B可以是16*37,也可以是24*29

如果A是51,那么B可以是14*37,也可以是22*29

如果A是47,那么B可以是10*37,也可以是18*29

如果A是41,那么B可以是4*37,也可以是12*29

如果A是37,那么B可以是8*29,也可以是20*17

如果A是35,那么B可以是6*29,也可以是8*27

如果A是29,那么B可以是6*23,也可以是10*29

如果A是27,那么B可以是4*23,也可以是10*17

如果A是23,那么B可以是4*19,也可以是10*13

如果A是17,那么B只能是4*13

如果A是11,那么B可以是2*9,也可以是5*6

只有A是17的时候只有一种情况,A是其他值的时候都至少有2种情况(我都只列出2种情况)

所以,答案是m=4,n=13

因为据说这是微软的面试题,所以我也编程求解了一下,发现上面的解法还有点漏洞。

实际上,根据S的第一句话,A没有11种情况,只有10种情况,要去掉其中的51,因为51=17+34

代码:

#include<iostream>
using namespace std;

const int low = 2, high = 99,s=high*2+1,p=high*high+1;
int ls[s], lp[p];

int main()
{
	int m, n;
	for (int i = 1; i < s; i++)ls[i] = 0;
	for (int i = 1; i < p; i++)lp[i] = 0;
	for (m = low; m <= high; m++)for (n = m; n <= high; n++)ls[m + n]++, lp[m*n]++;
	for (m = low; m <= high; m++)for (n = m; n <= high; n++)if (lp[m*n] == 1)ls[m + n] = 0;
	for (int i = 1; i < s; i++)if (ls[i]<2)ls[i] = -1; else ls[i] = 0;
	for (int i = 1; i < p; i++)if (lp[i]<2)lp[i] = -1; else lp[i] = 0;
	for (m = low; m <= high; m++)for (n = m; n <= high; n++)if (ls[m + n] == 0 && lp[m*n] >= 0)lp[m*n]++;
	for (m = low; m <= high; m++)for (n = m; n <= high; n++)if (lp[m*n] == 1 && ls[m + n] >= 0)ls[m + n]++;
	for (m = low; m <= high; m++)for (n = m; n <= high; n++)if (ls[m + n] == 1 && lp[m*n] == 1)cout << m << " " << n << endl;
	return 0;
}

这个程序的思想类似于前面的猜生日的表格法。

输出结果就是4 13,即为答案

三个班级

问题:

我们院一个年级三个班。有天偶遇一个同院的同级妹子,我问:“同学你是三班的吗?”她回答:“原来你是二班的啊!” 所以妹子在哪个班呢?

答案:

一班

无限多层嵌套推理

这题来自Matrix67大神的博客。

大家一定见过很多“我不知道,我也不知道,我还是不知道,我还是不知道,我知道了,我也知道了”的问题。但是,我想大家一定没有见过下面这样的问题。

A 、 B 两人在主持人 C 的带领下玩一个游戏。 C 向两人宣布游戏规则:“一会儿我会随机产生两个不同的形如 n – 1/2^k – 1/2^(k+r) 的数,其中 n 、 k 是正整数, r 是非负整数。然后,我会把这两个数分别交给你们。你们每个人都只知道自己手中的数是多少,但不知道对方手中的数是多少。你们需要猜测,谁手中的数更大一些。”这里,我们假设所有人的逻辑推理能力都是无限强的,并且这一点本身也成为了共识。 C 按照规则随机产生了两个数,把它们交给了 A 和 B ,然后问他们是否知道谁手中的数更大。于是有了这样的一段对话。

A :我不知道。
B :我也不知道。
A :我还是不知道。
B :我也还是不知道。
C :这样下去是没有用的!可以告诉你们,不管你们像这样来来回回说多少轮,你们仍然都没法知道,谁手中的数更大一些。
A :哇,这个信息量好像有点儿大!不过,即使知道了这一点,我还是不知道谁手中的数更大。
B :我也还是不知道。
A :我继续不知道。
B :我也继续不知道。
C :还是套用刚才的话,不管你们像这样继续说多少轮,你们仍然没法知道谁手中的数更大。
A :哦……不过,我还是不知道谁手中的数更大。
B :而且我也还是不知道。我们究竟什么时候才能知道呢?
C :事实上啊,如果我们三个就像这样继续重复刚才的一切——你们俩互相说一堆不知道,我告诉你们这样永远没用,然后你们继续互说不知道,我继续说这不管用——那么不管这一切重复多少次,你们仍然不知道谁手中的数更大!
A :哇,这次的信息量就真的大了。只可惜,我还是不知道谁的数更大一些。
B :我也还是不知道。
A :是吗?好,那我现在终于知道谁的数更大了。
B :这样的话,那我也知道了。而且,我还知道我们俩手中的数具体是多少了。
A :那我也知道了。

那么 , C 究竟把哪两个数给了 A 和 B ?

把两人手中可能的数(也就是 C 能产生出来的数)全都标在数轴上,则大概是这样:

你会发现这种情况非常有意思。最小的一批数是 0, 1/4, 3/8, 7/16, … ,这样数下去会有无穷多个数。但是,这无穷多个数的后面还有 1/2, 5/8, 11/16 等数,而且这一系列数本身又是无穷多的;在这无穷多个数的后面又还有 3/4, 13/16 等数,它们也有无穷多个……事实上,我们会遇到无穷多个类似于这样的无穷多个数,而最关键的就是,在这无穷多个无穷的后面,还有 1, 5/4, 11/8 等数。在新版的题目中, A 、 B 、 C 之间的游戏就是在这样的“场所”上进行的。

和旧题类似,在新题中,两人一遍又一遍地宣称自己“不知道”,本质上就是对序列 0, 1/4, 3/8, 7/16, … 从前往后进行排除。然而, C 跳出来说“这样下去是没有用的”,就意味着任何一方手上的数都不可能是该序列里的数,本质上相当于帮两人一下子排除掉了这无穷多种可能。如果此时 A 说自己“知道了”,那一定是因为他手里拿着的是除掉这无穷多个数之后剩下的最小的数,即 1/2 。然而, A 仍然说自己“不知道”,并且 B 也继续说自己“不知道”,并如此往复。此时,他们就相当于是在序列 1/2, 5/8, 11/16, … 上斗智了。而 C 又说了一遍刚才的话,本质上相当于又帮两人把这一系列数都排除掉了。两人继续开始考虑下一系列数的可能。

最后, C 告诉两人,这个模式重复多少次都不管用。于是,再下一系列的数,再下一系列的数,以及后面无穷多个系列的数,都被排除掉了。两人都知道了,他们手上的数都至少是 1 。当 A 再次说“不知道”的时候,说明他手中的数不是 1 ; B 再次说“不知道”,说明他手中的数既不是 1 也不是 5/4 ; A 说“知道了”,说明他手中的数是 5/4 和 11/8 中的一个; B 连具体的数也推出来了,说明此时 B 手上的数就是 11/8 。所以,两人手上的数分别是 5/4 和 11/8 。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
单词搜索迷宫(Word Search Puzzle)问题是一个经典的算法问题,其输入是一个二维的字符数组和一组单词,目标是找出字符数组网格中的所有单词。这些单词可以是水平的、垂直的或者是任意的对角线方向,所以需要查找8个不同的方向。解决这个问题的一种常见方法是使用回溯算法,具体步骤如下: 1. 遍历二维字符数组,对于每个字符,以其为起点开始搜索,搜索的方向包括水平、垂直和对角线方向。 2. 对于每个搜索到的单词,将其记录下来。 3. 重复步骤1和2,直到遍历完整个二维字符数组。 下面是一个使用C#语言实现的单词搜索迷宫算法的示例代码: ```csharp class WordSearchPuzzle { private char[,] grid; private HashSet<string> words; public WordSearchPuzzle(char[,] grid, HashSet<string> words) { this.grid = grid; this.words = words; } public void Solve() { int rows = grid.GetLength(0); int cols = grid.GetLength(1); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { Search(i, j, new StringBuilder()); } } } private void Search(int row, int col, StringBuilder sb) { if (row < 0 || row >= grid.GetLength(0) || col < 0 || col >= grid.GetLength(1)) { return; } sb.Append(grid[row, col]); string word = sb.ToString(); if (words.Contains(word)) { Console.WriteLine("Found '{0}' at [{1}, {2}] to [{3}, {4}]", word, row, col, row - sb.Length + 1, col - sb.Length + 1); } if (word.Length < 3) { Search(row + 1, col, sb); Search(row - 1, col, sb); Search(row, col + 1, sb); Search(row, col - 1, sb); Search(row + 1, col + 1, sb); Search(row - 1, col - 1, sb); Search(row + 1, col - 1, sb); Search(row - 1, col + 1, sb); } sb.Remove(sb.Length - 1, 1); } } // 使用示例 char[,] grid = new char[,] { {'t', 'h', 'i', 's'}, {'w', 'a', 't', 's'}, {'o', 'a', 'h', 'g'}, {'f', 'g', 'd', 't'} }; HashSet<string> words = new HashSet<string>() { "this", "two", "fat", "that" }; WordSearchPuzzle puzzle = new WordSearchPuzzle(grid, words); puzzle.Solve(); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值