题目描述

求解约瑟夫(Joseph)问题。有n个小孩围成一圈,给他们从1开始依次编号,从编号为1的小孩开始报数,数到第m个小孩出列,然后从出列的下一个小孩重新开始报数,数到第m个小孩又出列,…,如此反复直到所有的小孩全部出列为止,求整个出列序列。

如当n=6,m=5时的出列序列是5,4,6,2,3,1。n,m不大于20

输入

n m的值

输出

出列序列

样例输入

6 5

样例输出

5 4 6 2 3 1

问题解析

我们可以看到这个约瑟夫问题(即小孩报数)的问题,其实就是链表问题。我们通过这道题需要掌握的是循环单链表的写法(以c语言为例)

一、循环链表的写法

1.先定义链表的结构体

struct child{int data;struct child* next;
};

然后再全局变量定 “头节点”和“约瑟夫环的两个参数”

struct child* headnode;
int n,m;

下面,我们来定义两个函数,分别是“创建空节点”与“创建有数据的节点”

struct child* emptynode(){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = NULL;p->next = NULL;return p;
}struct child* createnode(int num){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = num;p->next = NULL;return p;
}

我们可以看出这两段代码的主要差别,其实就是p->data=NULL和p->data=num

接下来定义一个函数“createlistBytail”,以尾接法,创建循环单链表

void createlistBytail(struct child* headnode,int num){struct child* r=headnode;for (int i=2; i<=num; i++ ){struct child* s = createnode(i);s->next = r->next;r->next = s;r=s;} r->next = headnode;
}

那么其中需要注意的是,这段代码看似为单纯的创建单链表,其实我们在结尾处添加了一段代码

r->next = headnode;

这段代码保证了单链表的循环,也正因为这段代码,使得我们的单链表成功升级为循环单链表!

当然,为了检验我们的链表是否创建成功,我们可以写入这列代码,来遍历出链表的数据

void printlist(struct child* headnode){struct child* pMove = headnode;while(pMove) {printf("%d",pMove->data );pMove = pMove->next ;}
}

接下来,我们开始创建solve函数,实现小孩的报数功能

void solve(struct child* headnode,int n,int m){int i,j;struct child* p;struct child* q;for(i=1;i<=n;i++){p = headnode;j = 1;for(j=1;j<m-1;j++){p = p->next ;}q = p->next ;printf("%d ",q->data );p->next = q->next ;headnode = p->next ;}
}

其中,我们需要注意的是 我们在进行第二个for循环时,j<m-1这个数值不要搞错。我们为什么要j<m-1呢?因为我们要保证p是在第m个人的前一个人,这样我们就可以使q指向p->next,也就是我们想要的那个第m个人,实现精准查找,然后精准“删除”。但是问题来了,我们为什么不直接将p指向第m个人呢,这样我们直接输出p不就好了么:(。非也非也!你只是想到了输出数值的事,但是后面的事你却没能想到。

我们在这段函数的主要任务是什么呢?1.输出第m个人2.删除m,让m前一个人接上m后一个人3.将领头人headnode变成m的下一个人,也就是说从m的下一个人开始报数。这样我们不难发现我们将p设为m的前一个人,是要将p-next指向q->next,实现删除m的目的,因为我们节点的指针能指向某节点的后面,却指向不了节点的前面,所以哦我们需要这样的一个p指向m前一个点。

最后,我们编写主函数,将上面的函数包装进去

其中我们要注意的是,创建空节点与数据节点不在主函数里。

int main(){struct child* headnode = createnode(1);scanf("%d %d",&n,&m);createlistBytail(headnode,n);//printlist(headnode);solve(headnode,n,m);return 0;
}

这样,我们的代码就算结束了。最后,给大家奉上“小孩报数”(即约瑟夫问题)的完整版代码

#include<stdio.h>
#include<stdlib.h>
struct child{int data;struct child* next;
};struct child* headnode;
int n,m;struct child* emptynode(){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = NULL;p->next = NULL;return p;
}struct child* createnode(int num){struct child* p = (struct child*)malloc(sizeof(struct child));p->data = num;p->next = NULL;return p;
}void createlistBytail(struct child* headnode,int num){struct child* r=headnode;for (int i=2; i<=num; i++ ){struct child* s = createnode(i);s->next = r->next;r->next = s;r=s;} r->next = headnode;
}void printlist(struct child* headnode){struct child* pMove = headnode;while(pMove) {printf("%d",pMove->data );pMove = pMove->next ;}
}void solve(struct child* headnode,int n,int m){int i,j;struct child* p;struct child* q;for(i=1;i<=n;i++){p = headnode;j = 1;for(j=1;j<m-1;j++){p = p->next ;}q = p->next ;printf("%d ",q->data );p->next = q->next ;headnode = p->next ;}
}int main(){struct child* headnode = createnode(1);scanf("%d %d",&n,&m);createlistBytail(headnode,n);//printlist(headnode);solve(headnode,n,m);return 0;
}

问题 A: 约瑟夫问题(普及第一关模拟)相关推荐

  1. 2020.04.08【NOIP普及组】模拟赛C组24 总结

    2020.04.08 2020.04.08 2020.04.08[ N O I P NOIP NOIP普及组]模拟赛 C C C组 24 24 24 总结 概述: 这次比赛我 A K AK AK了,拿 ...

  2. JZOJ(中山纪念中学) 2018.02.02【NOIP普及组】模拟赛D组

    本次题目:2018.02.02[NOIP普及组]模拟赛D组 第一题 题目:第一题 公牛数字 题意: 求题目给出两个数字的乘积 分析: 这题明显只是考察学生的高精可我居然没做对,只要多练习几次,即可AC ...

  3. 2021-07-16 【普及组】模拟赛C组

    文章目录 2021.07.16[普及组]模拟赛C组 写在前面: T1: 题目大意: 正解: T2: 题目大意: 正解: T3: 题目大意: 正解: T4: 题目大意: 正解: 2021.07.16[普 ...

  4. 2021.07.16【普及组】模拟赛C组

    2021.07.16[普及组]模拟赛C组 文章目录 2021.07.16[普及组]模拟赛C组 前言 花生采摘 题目 解析 代码 FBI树 题目 解析 代码 火星人 题目 解析 代码 麦森数 题目 解析 ...

  5. 2020.02.07普及C组模拟赛4

    普及C组模拟赛4 **1.权势二进制 ** 题目描述 一个十进制整数被叫做权势二进制,当他的十进制表示的时候只由0或1组成.例如0,1,101,110011都是权势二进制而2,12,900不是. 当给 ...

  6. GMOJ - 2021.07.20【普及组】模拟赛C组 - 排座椅(seat)、传球游戏(ball)、立体图(drawing)、间谍派遣、seek

    文章目录 luogu博客链接 GMOJ - 2021.07.20[普及组]模拟赛C组 - 排座椅(seat).传球游戏(ball).立体图(drawing).间谍派遣.seek T1 排座椅(seat ...

  7. 纪中集训2020.01.13【NOIP普及组】模拟赛C组总结————My First Time Write Summary

    纪中集训2020.01.13[NOIP普及组]模拟赛C组总结 题目编号 标题 0 [NOIP普及组模拟]取值( numbers.pas/cpp) 1 [NOIP普及组模拟]数对(pairs.pas/c ...

  8. 2021-07-17【普及组】模拟赛C组 总结

    2021.07.17[普及组]模拟赛C组 总结 一.前言 今天第比赛还行,第1,2,3题都可以,但题2的一个特判没打出来就 WA 了. 二.题解 1. 开心的金明(happy) 01 背包模板,第一题 ...

  9. Python游戏开发:最强大脑第一关,数字华容道

    前言 freegames是Apache2许可的Python游戏集合,旨在用于教育和娱乐,完全是开源的,我们只要引用编写就好,当前在最强大脑的舞台上的第一关就是数字华容道,好多人都栽在了上面,如果你也想 ...

最新文章

  1. spring cloud微服务分布式云架构--hystrix的使用
  2. UICollectionViewController的用法1
  3. 全球农业发展中国方案-国际农民丰收节贸易会:榜样力量
  4. css 样式三元运算_CSS扩展语言——Sass入门指南
  5. 阿里巴巴对Java编程【OOP规约】的规约
  6. java quartz CronScheduleBuilder
  7. 为了自动驾驶,Uber每月烧钱1.3亿
  8. 《炬丰科技-半导体工艺》 光学镜片和玻璃部件的超声波清洗
  9. 网络通信基础知识简介
  10. 人脸美化随笔1——研究方向总结
  11. 15种方法活力一整天
  12. 华为linux连蓝牙鼠标,huawei蓝牙鼠标怎么样? 华为蓝牙鼠标连接使用教程
  13. 前端:注册校验页面(html+css+javascript)
  14. 网络切片技术缺点_什么是网络切片?
  15. Matlab + Gurobi入门
  16. 关于使用[MASK]做完形填空时需要注意的点
  17. 大话西游精彩影评(一)
  18. arm平台ubuntu环境下telnet安装及启动
  19. WebInspect评估版试用第1天
  20. 大清朝的微积分教材,堪称天书!

热门文章

  1. 程序员的情人节礼物:当天微软开始Build 2017登记
  2. 在传统.NET Framework 上运行ASP.NET Core项目
  3. c++ 二维矩阵 转vector_Python线性代数学习笔记——矩阵的基本运算和基本性质,实现矩阵的基本运算...
  4. linux c之动态打开链接库(dlopen dlsym dlclose)
  5. Android 之PackageManager框架
  6. vue data数据修改_Vue 超清晰思维导图(7张),详细知识点梳理!
  7. 地壳中元素含量排名记忆口诀_Nature:利用熔融包裹体的元素和同位素示踪俯冲带流体来源...
  8. 第一个发现我嫂子有喜的竟然是......
  9. 编程从业五年的十四条经验,句句朴实
  10. 备战美赛,这些你应该知道的知识点