第一次写这道题时用了几个变量一头扎进去就开始模拟,感觉挺有意思(擦汗)。
出圈
时间限制: 1 Sec | 内存限制: 128 MB
描述:
设有n个人围坐一圈并按顺时针方向从1到n编号,从第1个人开始进行1到m的报数,报数到第个m人,此人出圈,再从他的下一个人重新开始1到m的报数,如此进行下去直到所剩下一人为止。
输入
输入多行,每行2个数,分别表示n和m.
输出
计算每一行中最后剩下这个人的编号.
样例输入
10 3
样例输出
4
现在刚学会线性表一点皮毛,突然想到了约瑟夫,我天!这题和循环链表简直是天作之合啊。
算法
1.用尾插法建立一个循环链表,依次存入从1到n的编号。
2.从第一个结点开始报数,报数的结点被删除然后释放内存就可以了呀。
代码如下
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct node{
int data;
struct node *next;
}node;
typedef struct node LNode, *LinkList;
void CreateList_T(LinkList head, int n){
LinkList p, rear=head;
int num;
for(int i=0; i<n; i++)
{
p=(LinkList)malloc(sizeof(LNode));
p->data=i+1; //编号
rear->next=p;
rear=p;
}
rear->next=head->next;
}
int main()
{
LinkList head;
int i, e, select, m, k;
while(scanf("%d%d", &m, &k)!=EOF)
{
if(k==1)
printf("%d\n", m);
else
{
head=(LinkList)malloc(sizeof(LNode));
head->next=NULL;
CreateList_T(head, m);
LNode *p=head, *temp;
while(p!=p->next)
{
for(i=1; i<k; i++) //报数
{
p=p->next;
}
temp=p->next; //删除结点
p->next=temp->next;
free(temp);
}
printf("%d\n",p->data);
}
}
return 0;
}
然而
这个代码写得并不太好,我刚开始提交上去毫无疑问肯定是WA啊,找了半天才发现当出圈报数k=1时程序把所有人都划出圈了。
所以就有了上面的程序,把k=1的情况特殊处理,不过应该有还有更好的优化方式(除了特殊处理),先不管吧,AC了就睡觉。