约瑟夫问题(链表经典)
2016-11-22 16:49
141 查看
约瑟夫问题
总时间限制: 1000ms内存限制: 65536kB描述
约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。
输入
每行是用空格分开的两个整数,第一个是 n,第二个是 m ( 0 < m,n <=300)。最后一行是:0
0
输出
对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号
样例输入
6 2
12 4
8 3
0 0
样例输出
5
1
7
解析:这是一个很经典(经典就代表这道题是围绕着链表的核心展开)的链表问题,当然也可以不用链表来做。
首先要注意几点:
1.题目的要求是要围成一个圈,所以要有一点技巧处理:将最后一个的下一个指向第一个
2.每次踢出一个猴砸之后,都是从踢出的那个猴砸的下一个开始,而不是重新从第一个开始。(当时我就是因为这里理解错了一直没做出来,读题不仔细!)
大致思路:
1.先要定义一个结构体,为其创建一个链表。
2.然后是要写两个函数:1个是用来表示总猴砸数的改变,一个是用来表示报数猴砸的。
3.主函数就是读入数据,然后进入函数操作。
下面是代码:
#include using namespace std; int n,m; struct node{ //首先定义一个结构体 int n; node *next,*ahead; //使用两个指针为结点分配其位置 }; node*ahead;node*tail; void create(node* &head,int &n){ //第一个函数是用来表示所剩总猴子数的 node* tail=head; for(int i=1;i<=n;i++){ //开始从第一个循环 node* unit=new node; //定义一个新的结点 unit->n=i; //移动结点 tail->next=unit; tail=unit; } head=head->next; //每次都要移动开始的那一个 tail->next=new node; //因为开始的移动了,所以结尾的下一个也要移动到新的第一个去,形成一个环 node* unit=head; for(int i=1;i<=n;i++){ unit->next->ahead=unit; //相当与插入一个结点 unit=unit->next; //移动这个结点 } tail->next=head; //tips:技巧处理:将收尾连接,形成一个环 head->ahead=tail; } void s(node* &head,int &m){ //第二个函数是用来表示报数的猴子的 int x=n-1;int k=0; node* unit=head; while(x){ k++; if(k==m){ unit->ahead->next=unit->next;//这里是删除一个结点的意思 unit->next->ahead=unit->ahead; k=0; x--; } unit=unit->next; } cout<n<>n>>m; //输入猴子数n和所数到的那个数将会被退出圈子的数m while(n!=0||m!=0){ //满足条件就执行上面的函数 node*head=new node; create(head,n); s(head,m); cin>>n>>m; } return 0; }
相关文章推荐
- 约瑟夫问题链表解决方法(带有析构函数)
- 链表的几个经典问题-读《程序员面试攻略》
- 经典算法问题之约瑟夫问题
- 经典面试题:链表的相交与环问题
- 链表的三个经典问题
- 循环双向链表 及 约瑟夫问题的解决
- 链表经典问题汇总
- 经典面试题:链表的相交与环问题
- 经典面试题:链表的相交与环问题
- 链表经典问题汇总
- 循环链表解决约瑟夫问题
- 约瑟夫问题(单向链表)
- 约瑟夫问题(单向链表)
- 约瑟夫问题 链表解
- C/C++之单链表(含约瑟夫问题)经典总结
- 约瑟夫问题(Josephus问题)的递推O(n)解法、循环解法、单循环链表解法
- 约瑟夫问题(Josephus)java链表解决
- 利用单向环链表解决约瑟夫问题
- 环形链表解决约瑟夫游戏问题
- 链表的几个经典问题