您的位置:首页 > 文旅 > 旅游 > 什么事网页设计_外发加工网可靠么_营销推广网站推广方案_seo标题生成器

什么事网页设计_外发加工网可靠么_营销推广网站推广方案_seo标题生成器

2024/12/26 14:01:40 来源:https://blog.csdn.net/zl_dfq/article/details/144722030  浏览:    关键词:什么事网页设计_外发加工网可靠么_营销推广网站推广方案_seo标题生成器
什么事网页设计_外发加工网可靠么_营销推广网站推广方案_seo标题生成器

约瑟夫问题的一般形式是:N个人(或更一般地,对象)围成一圈,从某个人开始报数,每报到第M个人,该人就必须离开圈子,接着从下一个人重新开始报数,这个过程一直持续到只剩下一个人为止

一、简化版

N个人站在一行,从左到右顺次报数,报到 M 的人出列, 接着从下一个人重新开始报数,直到最后一个人报完数

1.输入N 与 M

#include <stdio.h>
int main ()
{int n, m;scanf("%d %d", &n, &m);return 0;
}

2.我们将这N个人编号 ,从 1 到 n

注意:数组下标从零开始,而从1开始报数

int order[n];for(int i = 0; i < n; ++i)order[i] = i+1;

2.定义计数器,并初始化为0

int num = 0;

3.循环

当计数器等于 M 时,需要复位为0. 然后从下一个人继续报数,直到最后一个人才停止报数,

显然 需要循环来实现 计数器的更新与计数

直到最后一个人才停止报数,这就是循环结束条件

	int k = 0;     //从第1个人开始,下标为零while (k < n)  //直到最后一个人报完数截至{++num;     //num初始化为0,开始报数   if (num == m){printf("%-3d", order[k]);  //-表示左对齐,3表示宽度为3num = 0;                  //计数器复位} ++k;                     //下一个人接着报数} 

连起来就是:

#include <stdio.h>
int main(void)
{int n, m;scanf("%d %d", &n, &m);int order[100];for (int i = 0; i < n; ++i)order[i] = i + 1;int num = 0;//计数器int k = 0;//第几个人while (k < n){++num;if (num == m){printf("%-3d", order[k]);num = 0;}++k;}return 0;
}

 以下是测试结果:

 

 

二、约瑟夫问题 

 1.关于下标

下标应介于 0到n-1 之间 ,想到取模   

k = (k+1) % n;

该表达式既完成了 下标加一操作, 又通过取模 将下标限制在 0到n-1 范围之内

2.循环结束条件

如果循环条件不变, 显然, 这将是一个死循环, 因为 下标k永远小于n

题目说,只要圈中只剩下一个人就停止报数, 那么, 圈中的人数就可以作为循环结束条件

但我们最好把 圈中人数大于0 作为循环结束条件

因为只剩下一个人的时候,就算他是一个人在报数,程序正确的话,最终也会得到出列顺序,这样就免去了我们单独在循环体外考虑 ta的下标k是多少 的麻烦

int in_circle = n;while(in_circle > 0)
{
......;
}

3.相应的人需要退出

我们如果不限制已经报数到M的人不再报数,

int num = 0;         //计数器
int in_circle = n;  //圈中的人数
int k = 0;           //从下标为0的人开始报数
while (in_circle > 0)
{++num;            //报数if (num == m){printf("%-3d", order[k]);num = 0;        //计数器复位--in_circle;   //人数少一}k = (k + 1) % n;   //下标更新
}

 

就会发现,编号会重复

所以这个时候,我们只需选择将编号清零,并判断即可

	int num = 0;//计数器int in_circle = n;int k = 0;while (in_circle > 0){if (order[k] != 0)  //只有在圈内,才能报数进行下一步操作{++num;if (num == m){printf("%-3d", order[k]);num = 0;--in_circle;order[k] = 0;}}k = (k + 1) % n;}

三、实践

 

 

#include <stdio.h>
#define MAXN 20void CountOff( int n, int m, int out[] );int main()
{int out[MAXN], n, m;int i;scanf("%d %d", &n, &m);CountOff( n, m, out );   for ( i = 0; i < n; i++ )printf("%d ", out[i]);printf("\n");return 0;
}/* 你的代码将被嵌在这里 */
void CountOff( int n, int m, int out[] )
{int in_circle = n;  //圈中人数int num = 0;        //计数器int order = 1;      //退出顺序static flag[100];   //标志位,假设最多只有100个人//静态数组,默认所有元素为0int i = 0;        //下标0表示第一个人while(in_circle > 0){if(!flag[i])   //只有在圈内的人才进行报数{++num;if(num == m){out[i] = order;  //排好顺序++order;in_circle--;     //人数少一num = 0;         //计数器复位flag[i] = 1;} }i = (i+1)% n;         //下一个人}
}

 

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com