由经典智力推算题中“11个教徒”的问题变形后的2个问题的javascript递归程序

经典智力推算题中“11个教徒”的问题:

有一次,一艘船在海上遇到风暴。为了减轻船的重量,摆在25名乘客面前的选择是把一部分人抛到海里。这样,船和剩下的人也许还能得救。谁也不愿意自动跳入海中。乘客里有11个教徒,其中一个想出了一个主意。他让所有的25人坐成一圈,然后依次报数“1、2、3”,规定报到“3”的人就被抛到海里。最后报数的结果有14人被抛下海。剩下的是这11个教徒。那么,他是如何安排这些剩余者的位置的?

由此变形出来的题目:

A)25个人排成一列,依次报数“1、2、3”,规定报到“3”的人就要出列。每轮都从队头的人开始报数,剩余到2人以后报数停止。问出列的人的编号依次是什么?

这题比较简单,直接贴代码了:

<html>
<head>

</head>
<body>
<script language="javascript">
var p=new Array();
var q=new Array();
var h,i,j,k=25,l=0;// k为队列初始长度
var count=1,bh=3;
for(i=1;i<=k;i++)
{
  p[i]=i;   //值与下标匹配
  //alert(p[i]);
}
function whoIsOut(j){
 if(p[j]>0)
  {
   if(j%bh==0)  //如果报号到逢3的
   {
     alert('第'+count+'轮出列的人标号为'+p[j]);
     p[j]=0;   //出列,记为0
    
    }
 
    else
    {
     
     l=l+1;      // //记录所有不为0的个数
    
     q[l]=p[j]; //保存对应的下标
     }
    
     j=j+1;
    
    if((j==k+1)&&(k>=bh))
    {
     for(j=1;j<l+1;j++)  
      { p[j]=q[j]; 
      }
     count=count+1;
     j=1;
     k=l;
     l=0;
    }
   
     whoIsOut(j);
    
  }
 
}
  whoIsOut(1);
</script>
</body>
</html>

B)25个人排成一圈,依次报数“1、2、3”,规定报到“3”的人就要出列。出列后继续顺延报数,剩余到2人以后报数停止。问出列的人的编号依次是什么?

思路:如果当队列长度刚好是3的倍数的时候,即退化为上面的习题,每次都从队头开始报数了;所以考虑队列长度不是3的倍数,则可以算出队列长度比3的倍数还多余几个,将多余的几个按原顺序调到队头,加上原来队头的顺序元素,即又可退化为上面的习题,从队头开始报数。一直递归下去,即可算出出列的人的编号。

代码:

<html>
<head>

</head>
<body>
<script language="javascript">
var p=new Array();  //待出列的队伍
var q=new Array(); //保留下一轮要出列的队伍
var h,i,j,k=25,l=0,m=1;  //k:队长;h:原队长多了多少,多余的部分就要调到队头去重新循环;i:赋初值时用的循环变量;j:本轮待比较的元素的下标;l:记录本轮出队后剩余的未出队的人的个数;m:记录下一轮要进入循环时的数组的下标
var count=1,bh=3; //count:记录出队的轮次;bh:逢几就出列的监视哨;

for(i=1;i<=k;i++)
{
  p[i]=i;   //值与下标匹配
 }

function whoIsOut(j){

 if((p[j]>0)&&(k>=bh)) //没有出列的且队长还允许出列的
  {
   
   if(j%bh==0)  //如果报号到逢bh的
   {
     alert('第'+count+'轮出列的人标号为'+p[j]);
    
     p[j]=0;   //出列,记为0
    
    }
 
    else
    {
     
     l=l+1;      // //记录所有不为0的个数
    
     q[l]=p[j]; //保存对应的下标
    
    }
    
     j=j+1;
    
    if((j==k+1)&&(k>=bh)) //j到了队尾了且队长要大于监视哨定义的长度(否则不够出列)
    { 
      m=1;
     if(k%bh>0) //原队长出列后是否有多余元素
     { 
      h=k%bh;   //多余元素的个数
         
     if(h>0)  //说明要将多余的个数需要调到前面去
     { 
           for(;h>0;h--)
       {
                p[m]=q[l-h+1]; 
                m=m+1;
        
       }
     }
     
     }
     //alert('m:'+m);
     for(j=m;j<l+m+1;j++) 
      {
        p[j]=q[j-m+1];  //加入其余的剩余元素,形成下一轮出队的数组
       }
     count=count+1;  //出队完成一轮,开始累加
     j=1;   //计数器还原
     k=l;   //队长退化为非0个数
     l=0; //非零数重新计数
   }
     whoIsOut(j); //递归
  }
}
  whoIsOut(1); //调用看效果
</script>
</body>
</html>

限于时间和技术,没有做成可以输入队列长度和逢几报号,并通过按钮来打印结果的形式。这两题算是很简单的题目,但是我做了很久,做完以后才知道原来挺简单的,呵呵。以此纪念我笨笨的算法,因为我在一点一滴地努力进步。。。。。。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值