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;
} 
京公网安备 11010502036488号