算法:报数游戏

报数游戏
问题描述:设有N个人围坐一圈并按顺时针方向从1到N编号,从第S个人开始进行1到M报数,报数到第M 个人时,此人出圈,再从他的下一个人重新开始1到M的报数,如此进行下去直到所有的人都出圈为止。现要打印出出圈次序。
要求实现函数:
void circle_sort (int n, int s, int m, int *p) 
输入:n 游戏总人数 s 报数的起始编号 m 报数的数值
输出:p 指向长度为n的数组,出圈次序保存在p指向的数组中


示例:n=7 s=2 m=3  出圈次序为:4 7 3 1 6 2 5 

#include <iostream>


using namespace std;


void circle_sort(int n, int s, int m, int *p );
void add1(int n, int &count , int *a);//实现下一位报数功能


int main()
{
    int i, n, s, m;
    cout << "Please input the number of people (n):";
    cin>>n;
    cout<<endl;


    cout << "Please input the start number  (s):";
    cin>>s;
    cout<<endl;


    cout << "Please input the circle number (m):";
    cin>>m;
    cout<<endl;


    int array[n];
    for(i = 0; i < n; i++)
    {
        array[i] = 0;
    }
    circle_sort(n, s, m, array);
    for(i = 0; i < n; i++)
    {
        cout<<array[i];
        cout<<"\t";
    }
    cout<<endl;
    return 0;
}
void circle_sort(int n, int s, int m, int *p )
{
    if(n < 1 || s > n || s < 1 || m < 1)
        return ;
    int number = 1 ,i;
    int count = s;
    int array[n+1];         //用数组array[]存放所有的序号
    for(i = 0; i < n+1; i++)//将数组中的每个元素初始化为相应的序号
    {
        array[i] = i;
    }
    while(number != n+1)      //报数,直到n个人全部被点出来
    {
        i = 1;


        if(number != 1) //如果不是第一次开始报数,每新一轮从下一位开始计数
            add1(n, count, array);


        while(i != m)       //报数1~m,出来一个
        {
            add1(n, count, array);
            i++;
        }


        p[number-1] = array[count];//找到新一轮要被删除的序号,保存在输出数组p[]
        array[count] = 0;




        number++;
    }


}


void add1(int n, int &count , int *array)
{
     if(count == n)  //如果到达数组尾,重新返回到array[1]
        count = 1;
    else
        count++;
    while(array[count] == 0)//跳过已经出去的序号
        {
            if(count == n)  //如果到达数组尾,重新返回到array[1]
                count = 1;
            else
                count++;
        }


}


———————————————————————————————————————————————————————————————————————————

                                                                                                                                                                                                                                                                                 2014/04/04 22:05

这实际上是Josephus问题,用循环链表比用数组要高效得多。


struct node{        //定义链表结点结构
    int elem;
    node *next;
    node(int x, node* t)
    {
        elem = x;
        next = t;
    }
};

typedef node* link;

void Josephus(int n, int s, int m)
{
    int i = 0;
    link head = new node(1,NULL);
    //head->next = head;
    link x = head;
    link p = NULL;
    for( i= 2; i <= n; i++)
    {
        x = (x->next = new node(i,NULL));
    }

    x->next = head;

    i = 1;
    x = head;
    while(i != s)
    {
         x = x->next;
         i++;
    }


    while(x != x->next)
    {
        for(i = 1; i < m-1; i++ )
            x = x->next;
        p = x->next;
        x->next = p->next;

        x = x->next;

        cout<<p->elem<<"\t";
        delete p;

    }
    cout<<x->elem<<"\t";
    delete x;
    head = NULL;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值