约瑟夫环总结

约瑟夫环

约瑟夫环算是比较经典的题目,我的解法是采用数组模拟链表
通过例题来分析吧
洛谷P1996约瑟夫问题

AC代码

#include<stdio.h>
int pre[101],nxt[101];
int main(){
	int m,n;
	scanf("%d %d",&n,&m);
	int i,j,k;
	for (i=1;i<=n;i++){
		pre[i]=i-1;//存放当前点的上一点
		nxt[i]=i+1;//存放当前点的下一点
	}
	pre[1]=n;nxt[n]=1;//让最后一点的下一点是第一点,第一点的上一点是最后一点,形成循环
	int now=n;//这样才能使在等一下的循环一开始now=1;见这行下面的第四行,保证第一次now=nxt[now]后now==1
	int l,r;
	for (i=1;i<=n;i++){
		for (j=1;j<=m;j++){
			now=nxt[now];
		}
		printf("%d ",now);
		l=pre[now];r=nxt[now];
		nxt[l]=r;pre[r]=l;
                //将now这个点去掉,让nxt[now]成为pre[now]的下一点,pre[now]成为nxt[now]的上一点,有点拗口,可以看下面的一张图(有点丑哈哈)
	}
	return 0;
}

2 出色的物理引擎 (100分)
卡罗拉最近沉迷于ark游戏,游戏中的地图上有n个浮空的石头围成了一圈,在优秀的物理引擎支持下,这些石头会自动落下。她发现石头落下的顺序是有规律的。一共有n个石头,从第一块石头开始数,数到第m个石头,那块就是第一个落下的石头;之后从第一个落下的石头后一个重新从1开始数,同样数到第m个石头,那个就是第二个落下的石头;以此类推。为了方便,对这些石头从1开始编号。卡罗拉现在想知道最后落下的是那一块石头?

输入格式:

输入包含两个整数n和m (1<=m,n<=1000)。

输出格式:

输出一 个整数,代表最后落下的石头的编号。

输入样例:

10 3

输出样例:

4

这题的处理方法和上面基本一模一样,只有在输出时不同,如果理解了上面那一题,可以拿这题练练手,就不再继续解释了(不好意思哈有点懒
AC代码

#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int pre[10007],nxt[10007];
int main()
{
	int i,j,k,l,r,m,n;
	scanf("%d%d",&n,&m);
	for(i=1;i<=n;i++){
		pre[i]=i-1,nxt[i]=i+1;
	}
	nxt[n]=1,pre[1]=n;
	k=n; 
	
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			k=nxt[k];
		}
		if (i==n) {
			printf("%d",k);
			break;
		}
		l=pre[k],r=nxt[k];
		pre[r]=l,nxt[l]=r;		
	}
	return 0;
}

洛谷P1145约瑟夫

#include<stdio.h>
int main(){
	int k,n;
	scanf("%d",&k);
	int m=k;
	int i,j,temp=1;
	while(temp){
		//假设序号为0~k-1都是好人,k~2*k-1都是坏人 
		m++;// m至少要大于1 
		int bekilled=0;//第一个被杀的序号 
		for (i=0;i<k;i++){
			//按照假设,序号为0~k-1都是好人,k~2*k-1都是坏人  
			bekilled=(bekilled+m-1)%(2*k-i);//下一个被杀的序号 
			if (bekilled<k){//如果被杀者序号小于k,则好人被杀,不符合题意 
				break;
			}
			if (i==k-1){//当被杀者(前面的代码保证了被杀的都是坏人)达到 k人,达到题设要求 
				temp=0;
			}
		}
	}
	printf("%d",m);
	return 0;
}
原文地址:https://www.cnblogs.com/xiao-qingjiang/p/12662982.html