猴子选大王问题

30个猴子站成一圈,从第一只猴子开始数到第三只猴子时,第三只猴子出圈;接着从第四只数,第六只猴子出圈…
按此规律,最后出圈的一个为猴王
此问题可用回溯算法求解

#include 
#include 
#define MAX 30
int monkey[MAX];

void init()
{
    int i;
    for(i=0;i<=MAX-1;i++)
    {
        monkey[i]=i+1;
        printf("%d ",monkey[i]);
    }
}

void output()
{
    int i;
    printf("\n\n猴子淘汰出圈的顺序是:\n");
    for(i=MAX-1;i>=0;i--)//数组最后的元素是第一个淘汰出圈的猴子
        printf("第%3d只猴子出圈!\n",monkey[i]);
    printf("猴王是第%3d只猴子!\n",monkey[i+1]);
}
int main()
{
    init();
    int i,j,k,temp;
    for(i=MAX-1;i>=0;i--)//经过上一轮循环monkey[i]=temp之后,上一轮循环得到的最末尾元素不再参与循环
    {
        for(k=1;k<=3;k++)//每次回溯三个值
        {
            temp=monkey[0];//先保存此时第一个元素的值
           for(j=0;j<i;j++)
           {
              monkey[j]=monkey[j+1];//元素向前推移(并非所有元素向前推移)
           }
           monkey[i]=temp;//最后一个元素变成循环开始时第一个元素的值
        }
    }
    output();
    return 0;
}

下面拿9只猴子来说明一下代码
经过init函数猴子站成一圈:1 2 3 4 5 6 7 8 9
(注:为了方便观看,出圈的猴子用“#”以及删除线表示
经过第一次循环(一次循环回溯三个值)后,数组变为:
4 5 6 7 8 9 1 2 #3
在第二次循环时,最末尾的3永远不再参与回溯,数组变为:
7 8 9 1 2 4 5 #6 3
第三次循环时,末尾的3和6不参与回溯,数组变为:
1 2 4 5 7 8 #9 6 3
第四次循环,3,6,9不参与回溯,数组变为:
5 7 8 1 2 # 4 9 6 3
第五次循环,数组变为:
1 2 5 7 #8 4 9 6 3
第六次循环,数组变为:
7 1 2 #5 8 4 9 6 3
第七次循环,数组变为:
7 1#2 5 8 4 9 6 3
(在第七次循环后剩下的猴子只剩下两个,为了方便最后一次循环,可以将数组写为:7 1 7 1#2 5 8 4 9 6 3
第八次循环,数组变为:
1 7 1# 7 2 5 8 4 9 6 3
因为在第七次循环中多加了一个 7 1,去掉一个“7 1” 只剩下了 1,所以最后的数组变为:1 # 7 2 5 8 4 9 6 3
那么猴王就是第1个了
当然,为了方便说明代码只是用来9只猴子选大王,所以在下面输出30只猴子选大王的结果:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

猴子淘汰出圈的顺序是:
第  3只猴子出圈!
第  6只猴子出圈!
第  9只猴子出圈!
第 12只猴子出圈!
第 15只猴子出圈!
第 18只猴子出圈!
第 21只猴子出圈!
第 24只猴子出圈!
第 27只猴子出圈!
第 30只猴子出圈!
第  4只猴子出圈!
第  8只猴子出圈!
第 13只猴子出圈!
第 17只猴子出圈!
第 22只猴子出圈!
第 26只猴子出圈!
第  1只猴子出圈!
第  7只猴子出圈!
第 14只猴子出圈!
第 20只猴子出圈!
第 28只猴子出圈!
第  5只猴子出圈!
第 16只猴子出圈!
第 25只猴子出圈!
第 10只猴子出圈!
第 23只猴子出圈!
第 11只猴子出圈!
第  2只猴子出圈!
第 19只猴子出圈!
第 29只猴子出圈!
猴王是第 29只猴子!!

你可能感兴趣的:(算法学习,算法)