约瑟夫环
约瑟夫环算是比较经典的题目,我的解法是采用数组模拟链表
通过例题来分析吧
洛谷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;
}
#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;
}