N只猴子,围成一圈,从1开始报数,数到M的猴子退出,最后剩下一只猴子就选为大王。
此题是约瑟夫环问题,可以推导出公式答案。不过,也可以用模拟过程的方法来解决。
首先定义猴子结点类型:
typedef struct st_Monkey
{
int SN;
struct st_Monkey * pNext;
struct st_Monkey * pPre;
}CMonkey;
为了方便,使用双向链表。
然后读入N和M,生成N只猴子围成一圈的初始数据。
CMonkey * InitMonkeys(int N)
{
int i=0;
if(N>0)
{
CMonkey * pHead, *pCur;
for(i=0;i<N;i++)
{
if(i==0)
{
pCur=(CMonkey*)malloc(sizeof(CMonkey));
pCur->pNext = NULL;
pCur->pPre = NULL;
pHead=pCur;
}
else
{
pCur->pNext=(CMonkey*)malloc(sizeof(CMonkey));
(pCur->pNext)->pPre = pCur;
pCur = pCur->pNext;
if (i==(N-1))
{
pCur->pNext = pHead;
pHead->pPre = pCur;
}
else
{
pCur->pNext = NULL;
}
}
pCur->SN = i+1;
}
return(pHead);
}
else
return(NULL);
}
模拟选猴王的过程:
CMonkey * ChooseMonkeyKing(CMonkey *pSt, int N, int M)
{
if(pSt!=NULL)
{
int i=1, j=1;
CMonkey *p0, *p1, *p2;
p1 = pSt;
p0 = p1->pPre;
p2=p1->pNext;
while(i<N)
{
if((j%M)==0)
{
printf("\n[del]%d", p1->SN);
p0->pNext = p1->pNext;
p2->pPre = p0;
free(p1);
p1 = p2;
p2 = p1->pNext;
i++; //只有猴子退出,才递增i,这样控制循环执行(N-1)次,最后只剩下一只猴子
}
else
{
p0 = p1;
p1 = p2;
p2 = p2->pNext;
}
j++;
}
return(p1);
}
else
return(NULL);
}
主函数,没啥好说的了。
int main(void)
{
int N=0, M=1;
printf("input N and M(N,M):");
scanf("%d,%d", &N, &M);
CMonkey * pHead = InitMonkeys(N);
CMonkey * pCur = pHead;
for(int i=1;i<=N;i++)
{
printf("SN=%d\t", pCur->SN);
pCur=pCur->pNext;
}
pCur = ChooseMonkeyKing(pHead, N, M);
if (pCur!=NULL)
printf("\nThe King is %d.\n", pCur->SN);
free(pCur);
printf("\n");
}