30个旅客同乘一个游轮出海Happy,因为严重超载,必须将全船一半的旅客投入海中,其余人才能幸免遇难。大家同意一种办法:30人围成一圈,由第一个人数起,依次报数,数到第9人,便把他投入大海中,然后再从他的下一个人数起,数到第9人,再将他扔进大海中,如此循环地进行,直到剩下15个乘客为止。
数组实现方式
void left_num(int* a,int n,int m,int f) //a为数组,n为总人数,m为出局密码,f为留下的人数
{
int out = 0,count = 0,i = 0; //out为出去的人数,count为报数,i为目前报到第几个人
int *p = a;int c=1;int d=0;
int num = 0;
for(num = 0;num < n;num++) {
*(a+num) = num+1;//为n个人编号1-n
}
while (out <f-1) {
if (*(p+i) != 0) {
count ++; //不等于0才报数+!
}
if (count == m) {
count = 0;
*(p+i) = 0;
out++; //报道m那么,出列人数out+1,且内容置0,报数置0
printf("%d\n",i+1);
}
i++;
if (i == n) {
i = 0; //到队尾重头开始
}
}
//输出剩下的人
for (num = 0; num < n; num++) {
if (*(a+num) != 0) {
printf("left num:%d\n",*(a+num));
}
}
}
如果留下的人不是一个,只需改变f的值,想留下多少人就可以留下多少人。
循环链表实现方式
int JoseDelete(HNode h, int M, int k,int f)//f为留下的人数
{ int i;
PNode p=h,q;
while(M>f)//节点剩下f个时停止出局
{
for(i=1;i<k-1;i++)
{
p=p->next;
}
q=p->next;
p->next=q->next;
printf("出局的人为:%d号\n",q->Num);
free(q);
p=p->next;
M--;//每出局一个结点减一
}
//printf("***************获胜者为:%d号***************",p->Num);
TraverseList(h,f);//打印15个留下的人
return 1;
}
循环链表同数组一样只需改变f的大小,便可改变,留下的人数。