问题描述
现有n个老鼠围成一圆圈,有一只猫从编号为1 的位置开始吃老鼠,每次都隔n-1个老鼠吃一个,请给出最后一个老鼠的编号?题目要求是任给老鼠数i,输出猫最后吃的老鼠的编号。
(n>2)
看来猫儿学会勤俭持家了。
这次再想几行代码抓到最长寿的老鼠,不好意思,我没想出来。 如果你知道,一定要告诉我。
先看源码。
/
typedef struct _MOUSE
{
__int64 num;
__int64 num10;
struct _MOUSE* pnext;
}MOUSE;
#define EAT_NUM 11
BOOL b_output_delnum = FALSE;
BOOL b_top = FALSE;
MOUSE* house(int num)
{
MOUSE* ph = NULL;
ph = (MOUSE*)malloc(sizeof(MOUSE));
if(ph==NULL)
{
return NULL;
}
ph->num = num;
ph->num10 = num;
ph->pnext = NULL;
return ph;
}
__int64
n_num(__int64 j)
{
//char out[124] ="";
__int64 i = 1;
__int64 num = j;
__int64 out = 0;
while(num>0)
{
out += (num%EAT_NUM)*i;
i *= 10;
num /= EAT_NUM;
}
return out;
}
__int64 num_10(__int64 j)
{
__int64 i = 1;
__int64 num = j;
__int64 out = 0;
while(num>0)
{
out += (num%10)*i;
i *= EAT_NUM;
num /= 10;
}
return out;
}
MOUSE*
sort(MOUSE* phead)
{
MOUSE* pout = NULL;
MOUSE* pnote = NULL;
MOUSE* pinsert = NULL;
while(phead)
{
if(pout==NULL)
{
pout = phead;
phead = phead->pnext;
pout->pnext = NULL;
}
else
{
pnote = pout;
pinsert = pnote;
while(pnote->num < phead->num)
{
pinsert = pnote;
pnote = pnote->pnext;
if(pnote==NULL)
break;
}
pinsert->pnext = phead;
phead = phead->pnext;
pinsert = pinsert->pnext;
pinsert->pnext = pnote;
}
}
return pout;
}
//
// num10 == 1, 10, 100
MOUSE*
expend(MOUSE* phead, __int64 num10, __int64 top)
{
MOUSE* pnew = NULL;
MOUSE* pend = NULL;
MOUSE* pnote = phead;
__int64 i = 1;
__int64 new_num = 0;
if(phead==NULL)
{
i = 0;
while(i<EAT_NUM)
{
if(i>= top)
{
b_top = TRUE;
break;
}
if(pend == NULL)
{
pend = pnew = (MOUSE*)malloc(sizeof(MOUSE));
if(pend == NULL)
return NULL;
}
else
{
pend->pnext = (MOUSE*)malloc(sizeof(MOUSE));
if(pend->pnext==NULL)
{
return NULL;
}
pend = pend->pnext;
}
pend->num = i;
pend->num10 = i+1;
pend->pnext = NULL;
i++;
}
return pnew;
}
while(pnote)
{
while(i<EAT_NUM)
{
new_num = pnote->num + i*num10;
if(new_num>= top)
{
b_top = TRUE;
break;
}
if(pend == NULL)
{
pend = pnew = (MOUSE*)malloc(sizeof(MOUSE));
if(pend == NULL)
return NULL;
}
else
{
pend->pnext = (MOUSE*)malloc(sizeof(MOUSE));
if(pend->pnext==NULL)
{
return NULL;
}
pend = pend->pnext;
}
pend->num = new_num;
pend->num10 = num_10(new_num)+1;
pend->pnext = NULL;
i++;
}
i=1;
pnote = pnote->pnext;
}
pend = phead;
while(pend->pnext)
{
pend = pend->pnext;
}
pend->pnext = pnew;
return phead;
}
//del 0 --- EAT_NUM-1
//
MOUSE*
eat(MOUSE* phead, int del)
{
int i=0;
MOUSE* pnote = phead;
MOUSE* pdel = NULL;
//int del = 0;
BOOL flag = FALSE;
if(NULL == phead->pnext)
return phead;
if(del==0)
{
phead = pnote->pnext;
if(b_output_delnum)
{printf(" %d,", pnote->num10);}
free(pnote);
pnote = phead;
i++;
}
i++;
while(pnote->pnext && pnote->pnext!=pnote)
{
if(i++==del)
{
pdel = pnote->pnext;
pnote->pnext = pnote->pnext->pnext;
if(b_output_delnum)
{printf(" %d,", pdel->num10);}
free(pdel);
pdel = NULL;
}
else
{
pnote = pnote->pnext;
}
if(b_top && pnote->pnext==NULL)
pnote->pnext = phead;
if(i== EAT_NUM)
{
flag = TRUE;
i=0;
}
}
return b_top ? pnote : phead;
}
int
my_cat2(int num)
{
int i = num;
int yu = 0;
__int64 num10 = 1;
int del = 0;
MOUSE* phead= NULL;
int result = 0;
BOOL bfirst = TRUE;
b_top = FALSE;
if(EAT_NUM<2 || EAT_NUM>10)
return -1;
do
{
phead = expend(phead, num10, n_num(num));
phead = sort(phead);
phead = eat(phead, del);
yu = (i - del )%EAT_NUM;
i = del + ((i-del)/EAT_NUM) *(EAT_NUM-1) + (yu?yu-1:0);
del = (EAT_NUM-yu)%EAT_NUM;
num10 *= 10;
}while( EAT_NUM>2 ? (phead->pnext!=phead) && (phead->pnext!=NULL) : i>1);
result = phead->num10;
return result;
}
///
源码ok, 写的有点随意。
主要函数简介
MOUSE* sort(MOUSE* phead){}
由于本方法要求 老鼠按编号排队,所以写了这个简单实现的排序函数, 没太考虑效率。
MOUSE* expend(MOUSE* phead, __int64 num10, __int64 top)
扩从老鼠队列, num10 依次输入1,10,100,1000,,, 这个不是十进制的,而是n进制的。 top 是 老鼠的总数, 也是n进制的。
举个例子吧。
n=3 , top =5 , phead链中有两个节点,节点的值为1,2, 经过本函数后,链中新添加1个节点 值为4(1+3)。 节点5(2+3) 没有加到链中是因为top =5 。 如果 top >5的话,节点5(2+3)也将加入链中。
再举个,
n=4, top =7, phead链中有三个节点,节点的值为1,2,3, 经过本函数后, 新添加2个节点 值为5(1+4), 6(2+4)。
差不多了。。 至于为什么 n=4时, phead链中有三个节点,嘿嘿,自己看看代码吧。
MOUSE* eat(MOUSE* phead, int del)
吃掉某些老鼠, 具体哪些被吃掉,取决于del 。 del 的取值范围 0 到 EAT_NUM-1。
老鼠链已经排好了,在这个函数中不关心节点的值,自关心节点在链中的位置,第一个节点位置为0,后边依次加1, 在del +EAT_NUM*i 位置上的节点将被吃掉。 对了,EAT_NUM的值是那个n,每n个老鼠吃一个的那个n。
int my_cat2(int num)
主要函数登场, num是老鼠总数。 调前面三个函数,并计算 每次调用时的参数。。。
关键是 eat()的第二个参数del, 过程挺曲折的。。。
yu = (i - del )%EAT_NUM; 是计算 eat()后的余数。
i = del + ((i-del)/EAT_NUM) *(EAT_NUM-1) + (yu?yu-1:0); 是计算eat()后的老鼠个数。
del = (EAT_NUM-yu)%EAT_NUM; 是 下次eat()时第几个老鼠倒霉。
ok. 不知下次猫儿咋个吃法。