约瑟夫环问题

1->数组解法

#include<cstdio>
#include<iostream>
using namespace std;
bool a[110];//a[x]表示x这个编号是否出局
int cnt,i,k;//cnt计数目前已经出局的人数,k表示已经报数的人数
int n,m;
int main()
{
    cin>>n>>m;//总共有n人,数到数字m时出局
    while(cnt!=n)//全部出局,程序结束
    {
        i++;//向右走
        if(i>n) i=1;//循环报数,n+1-->1
        if(a[i]==0)//如果i没有出局
        {
            k++;
            if(k==m)
            {
                cout<<i-1<<' ';//人从0开始编号
                a[i]=1;//出局
                k=0;//清空k,重新从1开始报数
                cnt++;
            }
        }
    }
  return 0;
}

2->循环链表解法

#include<cstdlib>
#include<iostream>
using namespace std;
typedef struct node
{
    int data;
    struct node *next;
}Node;//重命名
void ysflb(int n,int k)
{
    Node *head=NULL,*p=NULL,*r=NULL;//定义指针赋初值,如果没有申请空间则赋值为NULL
    head=(Node *)malloc(sizeof(Node));//链表的第一个元素,即头结点
    if(head==NULL)//申请失败
    {
        cout<<"Memory Failed";
        return ;
    }
    head->data=0;//编号为0
    head->next=NULL;
    p=head;//head不能动,用p代替
    //尾插法创建链表
    for(int i=1;i<n;i++)//缺n-1个结点,用for循环插入
    {
        r=(Node *)malloc(sizeof(Node));//申请一个结点
        r->data=i;
        r->next=NULL;
        p->next=r;//由p连接r
        p=r;//p向后走一步,方便下一个结点进入
    }
    p->next=head;//循环链表->尾巴连向头
    p=head;//方便while循环
    while(p->next!=p)//只有p一个结点
    {
        for(int i=1;i<k;i++)//报数
        {
            r=p;//r存p的前一个元素
            p=p->next;//p
        }
        cout<<p->data<<" ";
        r->next=p->next;//删除p结点
        p=p->next;//重新循环报数
    }
    cout<<p->data;//推出while时,剩余最后一个结点,输出
}
int main()
{
    int a,b;
    cin>>a>>b;
    ysflb(a,b);
    return 0;
}

3->递归解法

i!=1  ysf(n,k,i)=(ysf(n-1,k,i-1)+k)%n

i==1  ysf(n,k,i)=(k-1+n)%n     加n取模结果相同,防负数

//  i!=1  ysf(n,k,i)=(ysf(n-1,k,i-1)+k)%n
//  i==1  ysf(n,k,i)=(k-1+n)%n
#include<iostream>
using namespace std;
int ysf(int n,int k,int i)//总共有n个人,第i个报数为k的人出局
{
    if(i==1) return (k-1+n)%n;//第一个: 没有超过人数范围->k-1  超过范围-> (k-1)%n
    return (ysf(n-1,k,i-1)+k)%n;//第二次所走的编号+第一次的循环周期
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        cout<<i<<' '<<ysf(n,m,i)<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值