题目简介:
有n个旅客同乘一条船,因为船发生故障,最多只能留下一半旅客。大家议定如下办法:n个人围成一圈,由第一个人起,依次报数,报到m的人必须被扔进大海。如此循环。问最后哪些旅客仍留在船上?每个人都有一个m值,当他被扔进大海后,m的值改为这个人的m值。m的初值由第一个人决定。
输入格式:
输入共二行,第一行为人数n,第二行为n个整数,代表每个人的m值。
输出格式:
在一行中输剩下乘客的编号(用%3d格式输出)。
输入样例:
10
2 3 4 3 2 4 3 6 3 2
输出样例:
1 4 6 8 9
思路:
我最初的想法是建立一个循环链表,一个头指针L和两个循环指针p、q去循环删除数据,但是写着写着发现这个思路虽然可行,但要考虑的特殊情况多,比如遇到要删的数据为1时,又或是要删除首结点时。
所以倒不如不去真正的删除结点,而是在结构体中多加入一个元素来记录其状态,还留在船上的标记为1,扔海里的为0,在循环和输出时直接判断flag的值即可。
附上代码:
#include<stdio.h>
#include <stdlib.h>
//定义结构体
typedef struct LNode
{ int num; //记录编号
int data; //记录其m值
int flag; //记录状态(生1死0)
struct LNode *next;
}LNode, *LinkList;
int main()
{
int m,n,i,half,cnt=0;
scanf("%d",&n); //输入人数
//判断n的奇偶,题目中说最多只能留下一半的人,假如n=9,则要“删除”5人
if(n%2!=0) half=(n+1)/2; //为奇数时+1再除2
else half=n/2;
LinkList L,p,q;
L=(LNode *)malloc(sizeof(LNode));
scanf("%d",&L->data);
L->num=1; L->flag=1;
q=L;
for(i=1;i<n;i++) //建立循环链表
{
p=(LNode *)malloc(sizeof(LNode));
scanf("%d",&p->data);
p->num=i+1;p->flag=1;
q->next=p;
q=p;
}
q->next=L; //首位相连
//开始删除
m=L->data; //记录首结点的m值
p=L;
for(i=0;i<half;i++){
for(cnt=1;cnt<m;){ //cnt用于记录已经数的次数
if(p->flag!=0) //指到flag为1的人时cnt加1
cnt+=1;
p=p->next;
}
while(p->flag==0) p=p->next;//让p跳过flag已经为0的位置,防止flag重复置0
p->flag=0;
m=p->data; //记录被删除数据的m值,用于下次循环
p=p->next;
}
//判断状态,输出
p=L;
for(i=0;i<n;i++){
if(p->flag==1)
printf("%3d",p->num);
p=p->next;
}
return 0;
}
提交结果:
希望对你有帮助
若有不足请指出