Request:
一群猴子,编号是1,2,3 …m,这群猴子(m个)按照1-m的顺序围坐一圈。从第1只开始数,每数到第n个,该猴子就要离开此圈,这样依次下来,直到圈中只剩下最后一只猴子,则该猴子为大王。输入m和n,输出为大王的猴子是几号。
提示:
(1)链表解法:可以用一个循环单链表来表示这一群猴子。表示结点的结构体中有两个成员:一个保存猴子的编号,一个为指向下一个人的指针,编号为m的结点再指向编号为1的结点,以此构成环形的链。当数到第n个时,该结点被删除,继续数,直到只有一个结点。
(2)使用结构数组来表示循环链:结构体中设一个成员表示对应的猴子是否已经被淘汰。从第一个人未被淘汰的数起,每数到n时,将结构中的标记改为0,表示这只猴子已被淘汰。当数到数组中第m个元素后,重新从第一个数起,这样循环计数直到有m-1被淘汰。
(3)该问题为计算机科学中的经典问题,很多实际的问题可以抽象到这种模型上来。感兴趣的同学请搜索“约瑟夫问题”。
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}Monkey;
void InitList(Monkey *&L);
void CreateList(Monkey *& L, ElemType a[], int n);
void Pick(Monkey* L, int m, int n);
void DestoryList(Monkey *&L);
#endif // LIST_H_INCLUDED
#include <stdio.h>
#include "list.h"
int main(){
Monkey *Li;
int m, n, i;
scanf("%d%d", &m, &n);
printf("%d猴子以数%d选大王\n",m,n);
ElemType x[m];
for(i=0; i<m; i++)
x[i]=i+1;
CreateList(Li, x, m);
Pick(Li, m, n);
DestoryList(Li);
return 0;
}
#include <stdio.h>
#include "list.h"
#include <malloc.h>
//1.尾插法建链表
void CreateList(Monkey *&L, ElemType a[], int n){
Monkey *s, *r; //把r看成结点增量
int i;
L=(Monkey *)malloc(sizeof(Monkey));
r=L;
for(i=0; i<n; i++){
s=(Monkey *)malloc(sizeof(Monkey));
s->data=a[i];
r->next=s;
r=s;
}
r->next=L->next;
}
//2.销毁线性链表
void DestoryList(Monkey *&L){
Monkey *p=L->next;
free(p);
}
//3.选大王
void Pick(Monkey *L, int m, int n){
int k, i;
Monkey *p, *pre;
pre=L,p=L->next;
for(k=0;k<m-1;k++){
for(i=0;i<n-1;i++){
pre=p;
p=p->next;
}
pre->next=p->next;
p=p->next;
}
printf("大王是%d号猴子\n",p->data);
}
Result :
Gain :
void Pick(Monkey *L, int m, int n){
int k, i;
Monkey *p, *pre;
pre=L,p=L->next; //p=L->next
for(k=0;k<m-1;k++){
for(i=0;i<n-1;i++){ //i<n-1
pre=p;
p=p->next;
}
pre->next=p->next;
p=p->next; //p=p->next
}
printf("大王是%d号猴子\n",p->data);
}