约瑟夫环【队列】

1,了解C++中的队列


	queue<int> Q; //创建一个int类型的队列,队列名为Q
	
	Q.push()			//进队列(在队尾插入新元素) 
	Q.pop()				//出队列
	Q.empty()			//判断队空 
	Q.front()			//取队头元素(不删除队头元素)
	Q.back()			//返回队尾元素的值(不删除该元素)
	Q.size()			//返回队列中元素的个数 (这道题用不到)

2,题目

Problem 1206 约瑟夫环………………数构
Accepted: 898 Total Submit: 1564
Time Limit: 1000ms Memony Limit: 32768KB
Description
约瑟夫问题的一种描述是:编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个整数作为报数上限值,从第一个人开始顺时针自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他顺时针方向上的下一个人开始重新从1报数。如此下去,直至所有的人全部出列为止。试设计一个程序,求出出列顺序。
Input
先输入一个正整数T,表示有T组测试案例。每组测试案例的第一行是两个整数n、m,分别表示有n个人和一开始的上限值。第二行有n个正整数被空格隔开,表示每人持的密码。
Ouput
对每一组测试案例,先输出一行“Case id:”,id从1开始。然后按照出列顺序输出各人的编号,输出格式见样例。
Sample Input
1
5 2
1 3 4 3 2
Sample Output
Case 1:2->5->3->1->4

3,演示

1,刚开始有五个人,所以创建一个五个人的队列
在这里插入图片描述
2,第一步,第二个人出列
让1往后站
在这里插入图片描述
这时候该2往后站
可是2要出列;
所以要删除2;
在这里插入图片描述
3,2的密码是三,所以现在要让第三个人(也就是5)出列
过程应该是这样的:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3,5的密码是二,所以现在要让第二个人(也就是3)出列
过程:
在这里插入图片描述
在这里插入图片描述
3,3的密码是四,所以现在要让第四个人(也就是1)出列
过程:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
最后只剩下一个4了;

4,代码

#include<iostream>
#include<queue>
struct st
{
	int num;
	int password;
};
using namespace std;
int main()
{
	int T;
	cin>>T;
	while(T--)
	{
		int m,n;
		cin>>m>>n;
		queue<st> Q;//创建一个st类型的队列 
		st t;
		for(int i=1;i<=m;i++)
		{
			
			int password;
			cin>>password;
			
			t.num=i;
			t.password=password;
			
			Q.push(t);
		}
		int cut=0;
		while(Q.size()!=1)   	//直到队列里剩下1个人的时候停止
		{
			cut++;				//用cut=密码的时候,那个人就要离队了
			if(cut!=n)
			{
				t=Q.front();  
				Q.pop();		//删除队头
				Q.push(t);		//把刚才的队头放到队尾
			}
			else
			{
				n=Q.front().password;	//把出队的人密码记下来
				Q.pop();				//然后删掉他
				cut=0; 
			}
		}
		cout<<Q.front().num;
	} 
} 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
约瑟夫环是一个经典的问题,它描述了一群人围成一个环,每次数到指定的数字就出圈,直到只剩下一个人为止。这个问题可以用队列来模拟。 以下是使用C语言实现约瑟夫环队列形式的示例代码: ```c #include <stdio.h> #include <stdlib.h> typedef struct Node { int data; struct Node* next; } Node, *Queue; // 初始化队列 void initQueue(Queue* Q) { *Q = (Queue) malloc(sizeof(Node)); (*Q)->next = *Q; } // 入队 void enQueue(Queue Q, int data) { Node* newNode = (Node*) malloc(sizeof(Node)); newNode->data = data; newNode->next = Q->next; Q->next = newNode; Q = newNode; } // 出队 int deQueue(Queue Q) { if (Q->next == Q) { // 队列为空 printf("Queue is empty!\n"); return -1; } Node* p = Q->next->next; int data = p->data; Q->next->next = p->next; if (p == Q) { Q = Q->next; } free(p); return data; } // 约瑟夫环 void josephus(int n, int m) { Queue Q; initQueue(&Q); for (int i = n; i > 0; i--) { enQueue(Q, i); } int count = 0; while (Q->next != Q) { int data = deQueue(Q); count++; if (count % m != 0) { enQueue(Q, data); } else { printf("%d ", data); } } printf("\n"); free(Q); } int main() { int n, m; printf("Please enter the number of people and the number to count: "); scanf("%d%d", &n, &m); josephus(n, m); return 0; } ``` 在上面的代码中,我们使用了一个循环链表来模拟队列,并实现了队列的基本操作:初始化、入队、出队。在 `josephus` 函数中,我们先把所有人入队,然后进行循环,每次出队并计数,如果计数不到 `m`,就把这个人再次入队,否则就打印出这个人的编号。最后,当队列中只剩下一个人时,循环结束。 你可以尝试运行上面的代码,输入人数和每次要数的数字,看看约瑟夫环的结果是什么。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值