n人决斗问题

问题描述:

        n个人围成一圈,按顺序编上号( 1~n ) 。一共进行了n-1场决斗,最后一人胜出。规则如下:每轮只进行一场决斗,决斗人通过抽签选出,每人抽中的机会是均等的;每个人只能和他右边的人决斗;决斗负者被淘汰出圈,空位由他旁边的人补上。已知n个人之间的强弱关系由关系矩阵A来描述,如果 A(i,j)=1 表示第 i 人强于第 j 人 ;如果A(i,j)=0 表示第 i 人弱于第 j 人( 很明显如果A(i,j)=1,则必有A(j,i)=0 )。现在要求读入规模在 3≤ n ≤100 范围内的矩阵 A,计算和输出可能胜出的人数和方案。 

       先考虑这样一个问题,如果按照以上的规则决斗,n个人在决斗方式上会有多少种组合?如果组合数在可接受范围之内,那么就可以通过逐一罗列每一种组合并查询矩阵表A,来求得所要的最终输出数据。为简化问题,可先思考一下以下情况:

        假设有四个人,它们之间的联接方式为: A—B—C—D,决斗规则同上。第一场两两决斗后剩下三人,第一场决斗两两组合的方式有三种:A与B决斗,或者B与C决斗,或者C与D决斗。而决斗的结果则为:A与B决斗结果则有,A—C—D 或 B—C—D;B与C决斗结果则有,A—B—D 或 A—C—D ;C与D决斗结果则有,A—B—C 或 A—B—D,这六种情况 ( 实际上是有重复的,除去重复的,实际情况为四种 ),但由于A、B、C、D之间的强弱关系是已知的( 由矩阵A来确定 ),所以只会产生三种结果。也就是说在各元素强弱关系确定的情况下,决斗结果与决斗组合方式在数值上是相等的,而且也是一一对应的。 这可以为后面的推理提供依据。接下来对剩余的三人编号则联接为:1—2—3,此时,两两决斗的组合方式有两种:1与2决斗,或者2与3决斗。由于这两种组合方式是基于第一场决斗结果的,也就是说,第一场决斗的每一种结果,都会在接下来的第二场决斗中形成这样两种方式,所以两场决斗共有3x2=6种组合方式。

       这个问题也可以这样来看,把A、B、C、D之间的连线编号,假设AB间为1号,BC间为2号,CD间为3号则共有三条边,四个人需要决斗三场才能决出最后的胜者。每决斗一次会消失一条边,并淘汰一个人,那么这三场的决斗方式总数实际上就等于这三条边的全排列值:3x2x1 = 6。n个人围成一圈也只需要进行n-1场决斗,在数值上可以等价为n个人连成一线的方式。根据上面的讨论,这n个人的决斗方式的组合值为 (n-1)! 。根据已知条件,在最坏情况下n=100,那么就会有100! 场决斗,看来,绝对不可能用逐一罗列的方式来得到所要求的数据了。

       为方便讨论,先作以下假设:假设第 i 个人的左手边的那个人,称为 i 的上家,记为:Pi;第 i 个人的右手边的那个人,称为 i 的下家,记为:Ni 。

       其实,仔细想一下就可以知道,虽然n个人的决斗方式有(n-1)! 种,但这(n-1)! 种方式产生的结果最多不会超过n个( 容易想到,当A(i, Ni) = 1,  i = 1, 2, ...,n时,每个人都有可能成为最后的胜者,也就是说会有n种结果出现 )。所以之前提出的逐一罗列的方式实际上会产生大量的重复结果,而且绝大多数是重复的。另外逐一罗列用的是一种暴力解法,盲目搜索的一些搜索过程实际上是不必要而且可以避免的。

       经过以上思考就会想到,如果从结果的角度往回推,并充分利用矩阵 A 作为推理的依据,就会避免不必要的搜索过程,从而有可能得到在可接受时间内求得正确解的算法。

       想象一下,如果经过n-1场决斗,最后留下的是i ,需要什么条件?如果最后是i胜出,那么第n-1场决斗中的另一个人j必然要比i弱。也就是经过n-2场决斗后,只剩下2个人,一个是i,另一个是j,并且A(i,j) = 1;再继续深入,如果要保证在经过n-2场决斗之后,产生这样一个结果,需要在第n-3场决斗后产生一种什么局面?很显然这是一个具有递归结构的问题。为搞清这种结构,先把问题简化为由六个人组成的下图:

                                            

       先选择1号作为讨论对象,若已知 A(1, 4)=1,那么第5场决斗( n-1 )在1与4间展开时,可以保证这一结果。也就是说前面的4场决斗要保证2、3、5、6号都被淘汰。1号与4号将圈分成了两个弧,假设用(x, y) 表示整个圆经过两个人x与y 的弧,x表示弧的起点,y表示弧的终点。那么有 (4, 1) 表示弧4-5-6-1;(1, 4) 表示弧1-2-3-4。在弧(4, 1)中如果所有人要么弱于1要么弱于4,也就是没有一个人同时强于1号和4号,那么就一定有一种方案,使4号成为1号的上家,N4=1 (或者P1 = 4);如果至少有一个人,设此人为k,既强于4号又强于1号,而且无论采取何种方案,k一定会生存到(4,1)间所有其他人全部被淘汰,也即4与1之间只剩下k,那么N4=1就不可能成立,而使这一假设的方案( 第5场决斗在1与4之间展开 )不成立,并导致1 号不可能成为最后的胜出者( 要注意的是,在其它的方案中1号还有可能会成为最后的胜出者 )。 

       这个问题还可以这样来考虑,在假设1号胜出的情况下,选择了4号,而产生了弧(1, 4)和(4, 1),如果有方案使得N4=1且N1=4 那么1号一定胜出。为此,先讨论弧(4, 1)。如果在(4, 1)中能选出一个k ( k ∈ { k | A(k,4) = 0 或者 A(k,1) = 0 } )将此弧分为(4, k)与(k, 1),并且有方案使得N4=k且Nk=1,那么N4=1的情况一定会出现。与此类似如果在(1, 4)中能选出一个k‘ ( k’ ∈ { k‘ | A(k’,4) = 0 或者 A(k‘,1) = 0 } )将此弧分为(1, k’)与(k‘, 4),并且有方案使得N1=k’且Nk‘=4,那么N1=4的情况一定会出现,以此类推形成了此问题的递归结构。由于每选择一个中间点,此点就会将原来的弧划分为两段。因此,对选定的某个人作是否能最终胜出的递归判断过程,实际上就会生成一棵二叉树,二叉树中每个结点对应着一个划分。如果一个结点的两个子划分同时满足要求时,称这个结点满足要求。当根结点满足要求时,就称根结点胜出。( 每个划分实际上就是一种预设的决斗组合方式,而决斗组合方式与决斗结果是有对应关系的,参见上面的讨论 ) 下面详细讨论此二叉树。

       假设n个人围成一圈,并按逆时针方向顺序排列,以后的讨论都以此为基础。

       首先,这棵二叉树的结点可以由弧(x,y)来描述。 

       假设现在考虑1是否会最后胜出,并有弧(1, 3)和(3, 1)将圆分为两段( 其中A(1,3)=1 )。对(3, 1)来说,有5将其分为(3, 5)和(5, 1)两段,并有A(3, 5)=1且A(5,1)=1。对于这样一个划分既要讨论N3=5是否存在,又要讨论N5=1是否存在。因为,虽然5与1决斗必然会有5胜出,但当N3=5, A(3,5)=1时,只有N5=1才能使得N3=1成为可能。可描述为,如果在一段弧(x, y)中选择点k作为中点,将其分为(y, k)与(k, x)两段,并有A(x,k)=1且A(k,y)=1或者A(x, k)=1且A(k, y)=0( 也就是k既比x弱又比y弱 ),则需要同时对弧(x, k)和(k,y)作进一步递归。这里规定(x, k)为(x, y)的右子结点,(k, y)为(x, y)的左子结点。

       对一个结点(x, y)来说,有k使其被划分为(x, k)和(k, y),如果Nx=k 则(x, k)为叶子结点,如果Nk=y则(k,y)为叶子结点,如果Nx=y则(x,y)本身为叶子结点。如果一个结点为叶子结点,则直接返回真( 表示叶子结点弧的两个端点可以相邻 );如果一个结点是内结点,当两个子结点有一个为假就返回假,当两个子结点同时返回真时,需要测试A(x,k)和A(k,y)的值,若A(k,y)=1且A(x,k)=0则为假其余情况下为真,当为假时需要对当前结点作进一步探测,当为真时返回真( 假设当前只需只生成一个解决方案 )。

       每给出一个根结点,并判断其是否满足要求,就会生成一个二叉树,当二叉树中所有结点都是满足要求的,根结点必胜出。当根结点胜出时,对这棵二叉树进行中根遍历就可以得到一个完整的划分方案。

       这样,探测一个划分是否成功的算法就可以描述为:当一个划分为叶结点时返回真;当一个划分的左右结点都为真时划分返回真;当一个划分的左右结点只要有一个为假时,就需要重新选择另一个可能的中间点k,并根据它与x,y间的强弱关系作新的递归划分测试;如果包含在一个结点中的所有可能划分都失败,则返回假。

       一个给定的根结点,有可能存在多个满足要求的划分方案,因而需要逐一探测并输出。这里的难点是,给定一个根结点,如何记录并输出所有的成功划分方案。可以用另一棵动态树R来记录生成每棵二叉树的实际过程信息,帮助输出所有划分方案。例如:设上面所说的搜索二叉树的根结点为(1,3),此二叉树以假设1号胜出为基础,用树R来记录所有1号胜出方案( 二叉树 )的生成过程信息。设有p ∈{ i | A(1,i)=1,0≤i≤n },所有的p按逆时针依次排列,树R的根结点设置记数器,指向当前的p( 比如3 ),当当前p可满足时,令其子结点探测其他满足条件的方案。树R的每个结点都需要一个类似的计数器对应搜索二叉树的一个结点。

        如果要根据矩阵A得到所有的可行方案,就需要逐一对每个人作出划分假设,并输出每个划分假设的所有划分方案。

        用动态规划的方法可能不是唯一解。

       









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值