Posted on 2006-07-07 21:51
小乔的老哥 阅读(1610)
评论(0) 编辑 收藏 引用 所属分类:
深入C/C++
今天偶然在网上看到了猫抓老鼠问题,
当时也没多想,只觉得网上给出的程序的确有很多需要改进的地方,
就闷头闷脑的用 循环链表 和 递归 写了一个算法实现,后来发现
这个问题实际上是经典的约瑟夫环问题的变种,那个晕啊。而且有
很多数学的方式来改进。。。。5555。。。
看来算法部分要恶补,嗯嗯。。。
问题:
一、问题描述
现有n个老鼠围成一圆圈,有一只猫从任意位置开始吃老鼠,每次都隔一个老鼠吃,请给出最后一个老鼠的编号?题目要求是任给老鼠数n,输出猫最后吃的老鼠的编号。
二、我的解法
N只老鼠成循环链表,从第一只开始,每次隔一个节点,删去一个节点,这样一直删下去,
如果删去的节点的下一个节点已经是链表头了,则将链表头赋值为链表头的下下一个节点,
递归调用删除函数;如果删去的节点的下下一个节点才是链表头,则将链表头赋值为链表头
的下一个节 点, 递归调用删除函数;直至链表头的下下一个节点即是链表头,或链表头的下
一个节点就是链表头,break,输出链表头的编号。(这样做的目的是每次调用删除函数都是从
第一个节点删起。)
三 SOURCE:
// CatMousePro.cpp : Defines the entry point for the console application.
//
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#define MOUSENUM 60
struct Mouse* headMouse;
struct Mouse* pervMouse;
struct Mouse* cat;// currentMouse Point
bool eatType; // true means mouseNum is a 奇数,false is opposite
int lastMouseNum;
struct Mouse{
int Num;
struct Mouse* next;
};
void catEat(struct Mouse* headMouse)
{
if(headMouse->next->next == headMouse || headMouse->next == headMouse)
{
lastMouseNum = headMouse->Num;
return;
}
cat = headMouse;
//headMouse = cat->next;// because first mouse have been eated!
while(1)//not eat one circle
{
pervMouse = cat->next;
if(pervMouse->next == headMouse)
{
headMouse = headMouse->next;
pervMouse->next = headMouse;
break;
}
if(pervMouse->next->next == headMouse )
{
pervMouse->next = headMouse->next;
headMouse = headMouse->next->next;
break;
}
cat = cat->next->next;
pervMouse->next = cat->next;
}
catEat(headMouse);
}
int main(int argc, char* argv[])
{
Mouse mouse;
mouse.Num=1;
mouse.next = NULL;
headMouse = &mouse;
pervMouse = &mouse;
//inital mouse circle
for(int i=2;i<MOUSENUM+1;i++)
{
struct Mouse* newmouse = new struct Mouse;
newmouse->Num =i;
newmouse->next = NULL;
pervMouse->next = newmouse;
pervMouse = newmouse;
}
pervMouse->next = headMouse;
catEat(headMouse);
//at begin ,eat first mouse
printf("the last mouse num is:%d",lastMouseNum);
return 0;
}
顺便给出该问题的数学解法:
设有N只老鼠,找到大于N的最小的2的X次方(记为M),
然后 2N-M 就是结果,这样编程应该很简单了吧?