n m问题

问题描述:n个人围成一个圈,顺序排号,从第一个人开始报数,输入整数m,凡是报到m的人都应该退出圈子,问最后留下的是原来第几号的那位?

以下是用c语言来写,仅仅用循环和数组来解决这个问题:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i,k,m,n,num[50],*p,key;
    scanf("%d%d",&n,&key);

    p=num;
    for(i=0;i<n;i++)
    {
        *(p+i)=i+1;

    }

    i=0; //i为每次循环时的计数变量
    k=0;//k为按1,2,3报数时的计时变量。
    m=0;//m为退出人数。
    while(m<n-1)  //模拟游戏过程,这里用退出人数来控制循环结束条件。
    {
        if(*(p+i)!=0)
            k++;
        if(k==key)
        {
            *(p+i)=0;  //表示该序号的孩子退出游戏。
            k=0;
            m++;
        }

        i++;

        if(i==n)  i=0; //由于是一个圈子,所以要用这种方式来返回
    }

    while(*p==0)  //这里需要注意由于前面用指针遍历数组的方式原因,p一直指向数组的第一个元素
        p++;  //这个做法是直接改变了指针的指向,而前面的做法并没有改变。

    printf("the last one is NO.%d\n\n",*p);
    return 0;
}

以下是c++语言,并且这里用到了链表,更加容易理解:
#include <iostream>
using namespace std;

struct linklist
{
    int idata;
    linklist *next;
};

linklist *present,*head;   //这里通过全局变量来建立两个不同函数之间的交流。。。

void creat(int n);
void gamestart(int n,int m);
int main()
{
    int m,n;
    cin>>n>>m;
    creat(n);
    gamestart(n,m);
    cout<<"第"<<present->idata<<"个孩子将获得胜利!"<<endl;
    return 0;
}

/*linklist* creat(int n)
{
    linklist *head,*p1,*p2;
    int i;
    p1=new linklist;
    p1->idata=1;
    head=p1;
    p2=p1;
    for(i=1;i<n;i++)
    {
        p1=new linklist;
        p1->idata=i+1;
        p2->next=p1;
        p2=p1;
    }
    p1->next=head;

    return head;
}*/

void creat(int n)
{

    int i;
    head=new linklist;
    head->idata=1;
    present=head;
    for(i=1;i<n;i++)
    {
        present->next=new linklist;
        present->next->idata=i+1;
        present=present->next;
    }

    present->next=head;

    present=head;

}

void gamestart(int n,int m)
{
    linklist *pguard;
    while(n!=1)//自己想到了结点个数,却没有想到怎么通过结点个数控制循环
    {
        int j;
        for(j=1;j<m;j++)     //这里的实现是一个关键。。。通过一个指针不断的在链表之间变化来模拟游戏过程。
        {
            pguard=present;
            present=present->next;
        }
        pguard->next=present->next;
        delete present;
        present=pguard->next;   //从删除结点的下一个节点接着开始循环。
        n--;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39785575/article/details/79764384