请教一道编程题

时间:2022-08-06 10:28:00
有n个人按顺序排成一个圆圈,开始报数(从1到3),报到3的人退出圆圈,问:最后剩下的那个人是原来的第几号?

7 个解决方案

#1


是想要个程序吗

#2


http://paddy.myrice.com/program/34.htm

#3


约瑟夫问题

#4


http://expert.csdn.net/Expert/topic/2367/2367799.xml?temp=.9312097
不是已经问过了吗?

#5


// C语言版
#include <stdio.h>

void josephus(int iTotal, int iInter)
{
static int *iArr = new int[iTotal];
int j = 0; // j:间隔数iInter的游标
int iOut = 0;
for (int i = 0; ; ++i) // i:全部小孩iTotal的游标
{
i %= iTotal;

if (1 == iArr[i]) // 已经出去了
continue;
++j; // 此位置上的小孩还没有出去,j++;
if (iInter == j) // 已经输了iInter 个小孩,让这个小孩出去
{
iArr[i] = 1;
j = 0;
++iOut;
printf("%d\n",i);
}
if (iTotal == iOut) // 全出去了
return;
}
}

int main()
{
int iTotal = 0, iInter = 0;
printf("input total number: ");
scanf("%d",&iTotal);
printf("input internal: ");
scanf("%d",&iInter);
josephus(iTotal, iInter);
return 0;
}

#6


约瑟夫环问题
     约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一个正整数密码。开始时任选一个正整数做为报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m是停止报数,报m的人出列,将他的密码作为新的m值,从他的下一个人开始重新从1报数。如此下去,直到所有人全部出列为止。令n最大值取30。要求设计一个程序模拟此过程,求出出列编号序列。

#include <stdlib.h>
#include <alloc.h>

struct node
{
    int number; /* 人的序号 */
    int cipher; /* 密码 */
    struct node *next; /* 指向下一个节点的指针 */
};

struct node *CreatList(int num) /* 建立循环链表 */
{
    int i;
    struct node *ptr1,*head;

    if((ptr1=(struct node *)malloc(sizeof(struct node)))==NULL)
    {
        perror("malloc");
        return ptr1;
    }
    head=ptr1;
    ptr1->next=head;
    for(i=1;i<num;i++)
    {
        if((ptr1->next=(struct node *)malloc(sizeof(struct node)))==NULL)
        {
            perror("malloc");
            ptr1->next=head;
            return head;
        }
        ptr1=ptr1->next;
        ptr1->next=head;
    }
    return head;
}

main()
{
    int i,n=30,m; /* 人数n为30个 */
    struct node *head,*ptr;
    randomize();
    head=CreatList(n);
    for(i=1;i<=30;i++)
    {
        head->number=i;
        head->cipher=rand();
        head=head->next;
    }
    m=rand(); /* m取随机数 */
    i=0; /* 因为我没办法删除head指向的节点,只会删除head的下一节点,所以只能从0数起。*/
    while(head->next!=head) /* 当剩下最后一个人时,退出循环 */
    {
        if(i==m)
        {
            ptr=head->next; /* ptr记录数到m的那个人的位置 */
            printf("number:%d\n",ptr->number);
            printf("cipher:%d\n",ptr->cipher);
            m=ptr->cipher; /* 让m等于数到m的人的密码 */
            head->next=ptr->next; /* 让ptr从链表中脱节,将前后两个节点连接起来 */
            head=hea/d->next; /* head移向后一个节点 */
            free(ptr); /* 释放ptr指向的内存 */
            i=0; /* 将i重新置为0,从0再开始数 */
        }
        else
        {
            head=head->next;
            i++;
        }
    }
    printf("number:%d\n",head->number);
    printf("cipher:%d\n",head->cipher);
    free(head); /* 让最后一个人也出列 */
}
 
是这个问题的简化版本吧,以前的程序。

#7


//josephus问题是说,一群小孩围成一圈,任意假定一个数m,从第一个小孩起,
//顺时针方向数,每数到第m个小孩时,该小孩离开,小孩不断离开,圈子不断缩小
//最后一个小孩便是胜利者。究竟是第几个小孩呢?
#include<iostream>
using namespace std;
void main()
{
//建立小孩数组
const int num=0;//小孩数 
int interval;//每次数interval个小孩,便让小孩离开 
int a[num];//小孩数组
//给小孩编号
for(int i=0;i<num;i++)//小孩的编号只与小孩数有关 
a[i]=i+1;
//输入数小孩间隔 
cout<<"please input the interval:";//输入一个小孩个数
cin>>interval;
//将全体参加的小孩输出
for(int i=0;i<num;i++)//顺序输出开始时的小孩编号
cout<<a[i]<<","<<endl;
int k=1;//标识处理第k个离开的小孩 
int i=-1;//数组下标(下一个值0就是第一个小孩的下标)
//处理获胜的小孩
while(1)
{
//在圈中数interbal个小孩
for(int j=0;j<interval;)
{
i=(i+1)%num;//对下标加1求模
if(a[i]!=0)//如果该元素的小孩在圈中,则承认数数有效 
j++;
}
if(k==num) break;//该小孩是最后一个(胜利者)吗?
cout<<a[i]<<",";//输出离开的小孩编号
a[i]=0;//表示小孩已经离开
k++;
//预备处理下一个小孩 
}
//break语句跳转到此
cout<<"\nNo."<<a[i]<<"boy's won.\n";//输出胜利者
cin.get();
}
 
 

#1


是想要个程序吗

#2


http://paddy.myrice.com/program/34.htm

#3


约瑟夫问题

#4


http://expert.csdn.net/Expert/topic/2367/2367799.xml?temp=.9312097
不是已经问过了吗?

#5


// C语言版
#include <stdio.h>

void josephus(int iTotal, int iInter)
{
static int *iArr = new int[iTotal];
int j = 0; // j:间隔数iInter的游标
int iOut = 0;
for (int i = 0; ; ++i) // i:全部小孩iTotal的游标
{
i %= iTotal;

if (1 == iArr[i]) // 已经出去了
continue;
++j; // 此位置上的小孩还没有出去,j++;
if (iInter == j) // 已经输了iInter 个小孩,让这个小孩出去
{
iArr[i] = 1;
j = 0;
++iOut;
printf("%d\n",i);
}
if (iTotal == iOut) // 全出去了
return;
}
}

int main()
{
int iTotal = 0, iInter = 0;
printf("input total number: ");
scanf("%d",&iTotal);
printf("input internal: ");
scanf("%d",&iInter);
josephus(iTotal, iInter);
return 0;
}

#6


约瑟夫环问题
     约瑟夫环问题:设编号为1,2,3,……,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一个正整数密码。开始时任选一个正整数做为报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m是停止报数,报m的人出列,将他的密码作为新的m值,从他的下一个人开始重新从1报数。如此下去,直到所有人全部出列为止。令n最大值取30。要求设计一个程序模拟此过程,求出出列编号序列。

#include <stdlib.h>
#include <alloc.h>

struct node
{
    int number; /* 人的序号 */
    int cipher; /* 密码 */
    struct node *next; /* 指向下一个节点的指针 */
};

struct node *CreatList(int num) /* 建立循环链表 */
{
    int i;
    struct node *ptr1,*head;

    if((ptr1=(struct node *)malloc(sizeof(struct node)))==NULL)
    {
        perror("malloc");
        return ptr1;
    }
    head=ptr1;
    ptr1->next=head;
    for(i=1;i<num;i++)
    {
        if((ptr1->next=(struct node *)malloc(sizeof(struct node)))==NULL)
        {
            perror("malloc");
            ptr1->next=head;
            return head;
        }
        ptr1=ptr1->next;
        ptr1->next=head;
    }
    return head;
}

main()
{
    int i,n=30,m; /* 人数n为30个 */
    struct node *head,*ptr;
    randomize();
    head=CreatList(n);
    for(i=1;i<=30;i++)
    {
        head->number=i;
        head->cipher=rand();
        head=head->next;
    }
    m=rand(); /* m取随机数 */
    i=0; /* 因为我没办法删除head指向的节点,只会删除head的下一节点,所以只能从0数起。*/
    while(head->next!=head) /* 当剩下最后一个人时,退出循环 */
    {
        if(i==m)
        {
            ptr=head->next; /* ptr记录数到m的那个人的位置 */
            printf("number:%d\n",ptr->number);
            printf("cipher:%d\n",ptr->cipher);
            m=ptr->cipher; /* 让m等于数到m的人的密码 */
            head->next=ptr->next; /* 让ptr从链表中脱节,将前后两个节点连接起来 */
            head=hea/d->next; /* head移向后一个节点 */
            free(ptr); /* 释放ptr指向的内存 */
            i=0; /* 将i重新置为0,从0再开始数 */
        }
        else
        {
            head=head->next;
            i++;
        }
    }
    printf("number:%d\n",head->number);
    printf("cipher:%d\n",head->cipher);
    free(head); /* 让最后一个人也出列 */
}
 
是这个问题的简化版本吧,以前的程序。

#7


//josephus问题是说,一群小孩围成一圈,任意假定一个数m,从第一个小孩起,
//顺时针方向数,每数到第m个小孩时,该小孩离开,小孩不断离开,圈子不断缩小
//最后一个小孩便是胜利者。究竟是第几个小孩呢?
#include<iostream>
using namespace std;
void main()
{
//建立小孩数组
const int num=0;//小孩数 
int interval;//每次数interval个小孩,便让小孩离开 
int a[num];//小孩数组
//给小孩编号
for(int i=0;i<num;i++)//小孩的编号只与小孩数有关 
a[i]=i+1;
//输入数小孩间隔 
cout<<"please input the interval:";//输入一个小孩个数
cin>>interval;
//将全体参加的小孩输出
for(int i=0;i<num;i++)//顺序输出开始时的小孩编号
cout<<a[i]<<","<<endl;
int k=1;//标识处理第k个离开的小孩 
int i=-1;//数组下标(下一个值0就是第一个小孩的下标)
//处理获胜的小孩
while(1)
{
//在圈中数interbal个小孩
for(int j=0;j<interval;)
{
i=(i+1)%num;//对下标加1求模
if(a[i]!=0)//如果该元素的小孩在圈中,则承认数数有效 
j++;
}
if(k==num) break;//该小孩是最后一个(胜利者)吗?
cout<<a[i]<<",";//输出离开的小孩编号
a[i]=0;//表示小孩已经离开
k++;
//预备处理下一个小孩 
}
//break语句跳转到此
cout<<"\nNo."<<a[i]<<"boy's won.\n";//输出胜利者
cin.get();
}