news 2026/7/7 20:19:13

C语言之约瑟夫

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言之约瑟夫

题目描述

2k 个人站成一圈,从某个人开始数数,每次数到 m 的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人。现在有一圈人,k 个好人站在一起,k 个坏人站在一起。从第一个好人开始数数。你要确定一个最小的 m,使得在 k 个坏人均被杀死时 k 个好人都存活。

输入格式

一行一个整数 k。

输出格式

一行一个整数 m。

输入 3 输出 5 输入 4 输出 30 说明/提示 0<k<14

其中前 k 个人是好人(编号 1~k)
· 后 k 个人是坏人(编号 k+1~2k)
· 从第一个人(好人,编号1)开始数数
· 每次数到 m 的人被处决,然后从下一个人重新开始数
· 要求找到一个最小的 m,使得在处决完 k 个人后,剩下的 k 个人全是好人
· 换句话说:前 k 次处决必须全是坏人

#include<stdio.h> #define MAX_K 13 #define MAX_N (2*MAX_K)//代表的是总人数,最多为26个人。 int check(int k,int m) { int next[MAX_N+2],prev[MAX_N+2];//next[]表示每个人的后者,prev[]代表每个人的前者 int n=2*k;//总人数 int i; for(i=1;i<=n;i++){//给每个人都用遍历来赋上编号 next[i]=i+1;//编号为i的人的后一个人的编号为i+1 prev[i]=i-1;//编号为i的人的前一个人的编号为i-1 } next[n]=1;//编号为2k的人即为最后一个人的下一个人编号为第一个人的编号1 prev[1]=n;//编号为1的人的前一个人的编号为2k即n int p=1;//从编号1开始数 int L=n;//代表剩余人数 for(i=0;i<k;i++){//循环k次,是因为要处决k个坏人 int steps=(m-1)%L;//计算实际需要走的步数,即走这些步才数到m编号 int cur=p;//当前位置 int pre=prev[p];//当前位置的前一个 int j; for(j=0;j<steps;j++){走steps步找到被处决的人数 pre=cur;// cur=next[cur]; } if(cur<=k){//如果处决的人编号小于k即处决的是好人,不符合题意 return 0; } next[pre]=next[cur];//前一个位置的下一个即被处决的人的位置变成了被处决的人的下一个人 prev[next[cur]]=pre;//被处决的人的下一个人的前一个人变成了被处决的人的前面的人 p=next[cur];//被处决的人排除之后,下一个开始计数的位置变成了被处决的人的下一个人 L--;//剩余人数减少一个人 } return 1; } int main() { int k; scanf("%d",&k); int m; //代表数到m的人即会被处决杀死 for(m=k+1;;m++){//因为第一个人是好人,m肯定不会是应该被处决的人。对m开始进行枚举,如果碰到符合条件的m,即符合上述函数,则就输出m if(check(k,m)){ printf("%d\n",m); break;//因为要求的是最小的m,所以只要碰到第一个符合题意的输出,就不用再在后面判断了 } } return 0; }

一.上述代码采用双向循环链表。

什么是双向循环链表?

双向循环链表是一种特殊的数据结构:

· 双向:每个节点既知道下一个节点,也知道上一个节点
· 循环:链表的首尾相连,形成一个环
· 链表:一系列通过指针连接的数据节点

二.for(i=0;i<k;i++){
int steps=(m-1)%L;
int cur=p;//cur永远记录开始计数的人的位置
int pre=prev[p];
int j;
for(j=0;j<steps;j++){
pre=cur;//前一个人更新为当前位置,因为当前位置的人已经被杀死了
cur=next[cur];//当前开始计时位置为之前被杀死的人的后一个人
}//循环结束,cur就是被处决的人
if(cur<=k){
return 0;
}
next[pre]=next[cur];
prev[next[cur]]=pre;
p=next[cur];
L--;
}

详细解析上述部分代码:

1.因为从编号1开始走,走到编号2只需要走1步,即找到2只需要走1步,那么找到m只需要走m-1步。所以当m-1<L时,走的步数就是m-1,当人数为L时,走L步会回到起点,当m-1大于L时,走的步数即为余数。刚好满足上述式子。

2.

为什么初始化 pre = prev[p]?

· 在后续的循环中,pre 需要始终是 cur 的前一个人
· 开始时,cur = p,所以 pre 应该是 p 的前一个人

示例:

初始状态:
p=1,//从编号1开始数数 L=6,//剩余人数 m=3//每次数到m的人就会被杀掉
steps = (3-1)%6 = 2//数到m只需要实际走steps步

循环过程:
j=0: pre=1, cur=2
j=1: pre=2, cur=3

结果:cur=3(被处决的人)

上述循环结束后,cur表示的当前位置的人被处决,然后要想办法把该处决的人的编号排除。方法即为把被处决的位置变成被处决的后一个人,但后一个人的编号不变,只是位置改变。

当steps=0时,即循环不执行,直接处决当前位置cur即p

当m=1时,总是处决当前位置,即p=1时被处决,下次计数从第二个人开始,计数1,仍被处决,即当前位置被处决。

steps = (1-1)%L = 0
cur = p(被处决)

三.最后总结一下上述代码的思路:

用遍历对每个人进行编号,因为后续要利用双循环,所以要处理边界问题。因为排除被处决的人后要重新从下一个人开始计数,所以要定义一个变量p来表示从哪一个开始计数。然后对每一个人开始进行遍历,找应该被处决的人。定义走多少步可以找到处决者,为后续遍历找处决者提供基础。肯定要定义一个变量表示被处决者,又因为有双循环,前一个,后一个,当前者,索性把被处决者定义为当前者,当前者初始化为计数的位置,而这刚好便于去除当前者后的计数位置为下一个人,同时更好找到处决者时好改变前者后者的位置。既然有前者和后者,所以要定义。最后去除当前者,改变剩余者的位置。最后直到把所有的坏人都除掉之后,当前位置变成小于k的值,跳出该函数。只要输入的m符合题意,则就会返回1,用于后续主函数的输出。

写这篇的时候好痛苦啊!!!用了两个小时。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/6 21:36:27

C++类和对象(三):核心特性与实战技巧

在 C 面向对象编程中&#xff0c;类与对象的进阶特性是写出高效、规范代码的关键。本文将聚焦构造函数细节、静态成员、友元、内部类、匿名对象及编译器优化等核心知识点&#xff0c;结合实例拆解原理&#xff0c;帮你彻底吃透这些易混淆的重点。一、再谈构造函数&#xff1a;初…

作者头像 李华
网站建设 2026/7/7 17:43:25

防止ssh断开服务器进程

在锁屏或长时间不操作时&#xff0c;导致VS Code SSH连接断开的主要原因是网络中的防火墙或路由器会关闭长时间空闲的连接。你可以通过配置“心跳包”和让后台进程独立运行这两种方法来解决。下面我将分别介绍这两种方案的具体操作。方案一&#xff1a;配置SSH心跳保活&#xf…

作者头像 李华
网站建设 2026/7/7 18:33:53

AVL-CRUISE纯电动汽车仿真终极指南:3步掌握动力性经济性分析

AVL-CRUISE纯电动汽车仿真终极指南&#xff1a;3步掌握动力性经济性分析 【免费下载链接】AVL-CRUISE纯电动汽车动力性经济性仿真资源介绍分享 本资源文件详细介绍了如何利用AVL-CRUISE软件进行纯电动汽车的动力性经济性仿真。通过该文件&#xff0c;您将学习到如何设置仿真模型…

作者头像 李华
网站建设 2026/7/6 22:16:47

李宏毅深度学习入门-学习笔记-第1章 机器学习基础

教程地址&#xff1a; 机器学习任务攻略_哔哩哔哩_bilibili datawhalechina/leedl-tutorial: 《李宏毅深度学习教程》&#xff08;李宏毅老师推荐&#x1f44d;&#xff0c;苹果书&#x1f34e;&#xff09;&#xff0c;PDF下载地址&#xff1a;https://github.com/datawhale…

作者头像 李华
网站建设 2026/7/7 20:08:43

macOS微信通知优化全攻略:打造高效工作环境

macOS微信通知优化全攻略&#xff1a;打造高效工作环境 【免费下载链接】electronic-wechat :speech_balloon: A better WeChat on macOS and Linux. Built with Electron by Zhongyi Tong. 项目地址: https://gitcode.com/gh_mirrors/el/electronic-wechat "正在专…

作者头像 李华
网站建设 2026/7/7 6:26:50

VerlEngine实战指南:彻底关闭Qwen3模型的思维链模式

VerlEngine实战指南&#xff1a;彻底关闭Qwen3模型的思维链模式 【免费下载链接】verl verl: Volcano Engine Reinforcement Learning for LLMs 项目地址: https://gitcode.com/GitHub_Trending/ve/verl VerlEngine作为火山引擎推出的大语言模型强化学习框架&#xff0c…

作者头像 李华