1.n个人喊号,从1开始,喊到m号的人淘汰,求最后剩下的一个人的编号
思路:n个人用数组flag[n+1]保存,从1到n,依次按下标保存,即下标即为人,然后全部置1,喊到m的 置零,最后只剩1个时,遍历数组,flag[i]=1,则输出i,为最后一人;
具体代码:
#include<iostream>//只剩一人的约瑟夫环问题
#include<vector>
using namespace std;
int main()
{
	int n;
	while (cin >> n)
	{
		//int* a = new int[n + 1];
                vector<int>a(n+1,1);
		int t = 3;
		//for (int i = 1; i <n+1; i++)//全部置1
			//a[i] = 1;
		int m = 1, i = 1, j = n;//j为人数,m为数组下标,i为喊到的号数
		while (j > 1)
		{
			if (a[m] == 0)
			{
				m %= n;//先求模,再++可以避免当假如n=10,m=9时,如果先++,m=10,再求模m=0,m=10就会被跳过
				m++;
			}
			else
			{
				if (i == t)
				{
					a[m] = 0;
					j--;
					i = 1;//i=m时,下一个人该喊1
					m %= n;
					m++;
					continue;
				}
				i++;
				m %= n;
				m++;
			}
		}
		for (i = 1; i < n; i++)
                {
			if (a[i] == 1)
                        {
				cout << i << endl;
                                break;
                        }
                }
	}
	return 0;	
}
2.100人乘船,船漏水,需要抛下50人下海,剩下50个人才会没事,排一圈,从1还是喊号,喊到9的人跳海,下一个人从1还是继续喊,直到只剩50人
思路:思路大体和上题一样,变成j>50就行,遍历=1的输出
代码:
//剩多人的约瑟夫环问题,输出淘汰人的编号
#include<iostream>
#include<vector>
using namespace std;
int main()
{
	int n, k;
	while (cin >> n >> k)
	{
		vector<int>a(n+1, 1);
		int j = n, i = 1, m = 1;
		while (j > n / 2)
		{
			if (a[m] == 0)
			{
				m%=n;
				m++;
			}
			else
			{
				if (i == k)
				{
					i = 1;
					a[m] = 0;
					j--;
					m %= n;
					m++;
					continue;
				}
				i++;
				m %= n;
				m++;
			}
		}
		for (i = 1; i < n + 1; i++)
		{
			if (a[i] == 1)
				cout << i << ' ';
		}
		cout << endl;
	}
	return 0;
}

3.利用队列快速解决问题,先全部入队,然后出队再入队,第9个人出队不入队,如此循环,当队列大小只剩50时,输出这个队列
上代码!
//队列解决约瑟夫问题
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
	queue<int>q;
	int n, k;
	while (cin >> n>>k)
	{
		int cnt = 1;
		for (int i = 1; i < n + 1; i++)//进队
			q.push(i);
		while (q.size()> n / 2)
		{
			if(cnt!=k)//喊号不=9时,出队入队
			{ 
				int t = q.front();
				q.push(t);
				q.pop();
				cnt++;
			}
			else//等于9, cnt=1,开始下一轮喊号
			{
				cnt = 1;
				q.pop();
			}	
		}
		int len = q.size();
		//vector<int>a(len);
		for (int i = 0; i < len; i++)
		{
			
			cout << q.front()<<' ';
			q.pop();
		}
		
		cout << endl;

	}
	return 0;
}
此时输出的序号有一部分不是按序的,如果题目输出有要求按序
代码进行部分修改
int len = q.size();
vector<int>a(len);
for (int i = 0; i < len; i++)
{
	a[i] = q.front();
	//cout << q.front()<<' ';
	q.pop();
}
sort(a.begin(), a.end());
for (vector<int>::iterator it = a.begin(); it != a.end(); it++)
    cout << *it << ' ';
cout << endl;
return 0;
}

不想用sort,可以直接用set容器,自动排序
修改部分代码:
添加头文件#include<set>
                set<int>a;
		for (int i = 0; i < len; i++)
		{
			a.insert( q.front());
			//cout << q.front()<<' ';
			q.pop();
		}
		//sort(a.begin(), a.end());
		for (set<int>::iterator it = a.begin(); it != a.end(); it++)
			cout << *it << ' ';
		cout << endl;

	}
	return 0;
}
链表解决方案以后再更新
2021.914更新链表解法
#include<iostream>
using namespace std;
struct list
{
	int pos;
	list* next;
};
int main()
{
	int n = 13, a;
	list* head, *p;
	head = new list;
	cin >> a;
	head->pos = a;
	head->next = head;
	p = head;
	for (int i = 2; i <= n; i++)
	{
		p->next = new list;
		p = p->next;
		p->pos = i;
		p->next = head;
	}
	while (p != p->next)
	{
		for (int i = 1; i < 3; i++)
			p = p->next;
		list* pre = p->next;
		p->next = p->next->next;
		delete(pre);
	}
	cout << p->pos;
	return 0;
}