蓝桥杯 算法提高 奥运会开幕式
问题描述
学校给高一(三)班分配了一个名额,去参加奥运会的开幕式。每个人都争着要去,可是名额只有一个,怎么办?班长想出了一个办法,让班上的所有同学(共有n个同学)围成一圈,按照顺时针方向进行编号。然后随便选定一个数m,并且从1号同学开始按照顺时针方向依次报数,1, 2, …, m,凡报到m的同学,都要主动退出圈子。然后不停地按顺时针方向逐一让报出m者出圈,最后剩下的那个人就是去参加开幕式的人。
要求:用环形链表的方法来求解。所谓环形链表,即对于链表尾结点,其next指针又指向了链表的首结点。基本思路是先创建一个环形链表,模拟众同学围成一圈的情形。然后进入循环淘汰环节,模拟从1到m报数,每次让一位同学(结点)退出圈子。
输入格式:输入只有一行,包括两个整数n和m,其中n和 m的含义如上所述。
输出格式:输出只有一个整数,即参加开幕式的那个人的编号。
样例输入
8 3
样例输出
7
题目思路
先用尾插法初始化链表,再通过循环将对应的学生淘汰,只留下最后一个学生。
代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef struct stu{
struct stu *next;
int flag;
}Stu;
Stu *initlist(int n){//尾插法初始化链表
Stu *p,*s;
s=(Stu *)malloc(sizeof(Stu));
s->flag=1;
s->next=s;
for(int i=2;i<=n;i++){
p=(Stu *)malloc(sizeof(Stu));
p->flag=i;
p->next=s->next;
s->next=p;
s=p;
}
return s->next;
}
Stu *del(Stu *p){//淘汰学生的处理
Stu *r=p->next;
while(r->next!=p){//找到被淘汰的学生的前一个学生
r=r->next;
}
r->next=p->next;
free(p);
return r->next;
}
int main(){
int n,m,k,i=1;
Stu *stu,*p;
scanf("%d%d",&n,&m);
stu=initlist(n);
p=stu;
k=n;
while(k>1){
if(i==m){
p=del(p);
i=1;
k--;
}
else{
p=p->next;
i++;
}
}
printf("%d",p->flag);
return 0;
}