一、约瑟夫问题
题目:设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到m的人又出列,如此重复,直到所有的人全部出列为止。
Josephus问题是:对于任意给定的n,s,m,求出按出列次序得到的n个人员的序列。
二、题解
1.队列类定义:
class Queue{
private:
int mSize;
int front;
int rear;
int* queue;
public:
Queue(int size){
mSize=size+1;
queue = new int[mSize];
front = rear = 0;
}
~Queue(){
delete[] queue;
}
//入队
bool enQueue(const int item){
if(((rear+1)%mSize) == front)
return false;
queue[rear]=item;
rear=(rear+1)%mSize;
return true;
}
//出队
bool deQueue(int &item){
if(front==rear)
return false;
item=queue[front];
front=(front+1)%mSize;
return true;
}
//获取队首元素
bool getFront(int &item){
if(front==rear)
return false;
item=queue[front];
return true;
}
};
2.解法
代码如下(示例):
class Solution{
public:
void josephus(int n,int s,int m){
Queue* q = new Queue(n);
int counter = 1;
int item=0;
//初始化1->n的队列
for(int i=0;i<n;i++){
q->enQueue(i+1);
}
//找到第一次开始的位置
while(counter<s){
q->deQueue(item);
q->enQueue(item);
counter++;
}
counter=1;
while(1){
//找到下一个报数到m的位置
while(counter<m){
q->deQueue(item);
q->enQueue(item);
counter++;
}
q->deQueue(item);
//将结果输出
cout<<item<<" ";
//如果返回false说明队列为空,跳出循环
if(!q->getFront(item))
break;
counter=1;
}
}
};
3.主函数测试
int main() {
int n,s,m;
std::cin>>n>>s>>m;
Solution solution;
solution.josephus(n,s,m);
return 0;
}
测试输入5 1 2 结果: