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; }