7-5 jmu-报数游戏 (15 分)

报数游戏是这样的:有n个人围成一圈,按顺序从1到n编好号。从第一个人开始报数,报到m(m<n)的人退出圈子;下一个人从1开始报数,报到m的人退出圈子。如此下去,直到留下最后一个人。其中n是初始人数;m是游戏规定的退出位次(保证为小于n的正整数)。要求用队列结构完成。输出数字间以空格分隔,但结尾不能有多余空格。

输入样例:

5 3

输出样例:

3 1 5 2 4

输入样例:

5 6

输出样例:

error!


看到这个题,想到是用STL set来做
下面是最开始的代码
#include <iostream>
#include<set>
using namespace std;
int main()
{
    set<int> s;
    int m, n;
    cin >> n >> m;
    if (m >= n) {
        cout << "error!";
        return 0;
    }
    for (int i = 0; i < n; i++) {
        s.insert(i + 1);
    }
    set<int>::iterator it;
    it = s.begin();
    int flag = 0;
    while (s.size() != 0) {
        for (int i = 1; i < m; i++) {
            if (!(it != s.end())) {
                it = s.begin();
            }
            it++;
        }
        if (!(it != s.end())) {
            it = s.begin();
        }

        if (flag == 0) {
            cout << *it;
            flag = 1;
        }
        else {
            cout << " " << *it;
        }

        int c = *it;
        s.erase(c);
        int j = 1;
        it = s.find((c + 1) % n);
        if (!(it != s.end())) {
            it = s.begin();
        }
    }
}

测试结果:

 

但是看这一句  it = s.find((c + 1) % n);  假设(c+1)%n在set中没有找到的话,返回给it的地址就是s.end()  但是假设c+1没找到后面还有c+2的话就会出错,所以我手写了一个测试点,n=8,m=3。

按照题目意思推理得出: 3 6 1 5 2 8 4 7

但是按照我写的代码得出的结果是:3 6 1 5 7 8 2 4

所以改进版代码为:

#include <iostream>
#include<set>
using namespace std;
int main()
{
    set<int> s;
    int m, n;
    cin >> n >> m;
    if (m >= n) {
        cout << "error!";
        return 0;
    }
    for (int i = 0; i < n; i++) {
        s.insert(i+1);
    }
    set<int>::iterator it;
    it = s.begin();
    int flag = 0;
    while (s.size() != 0) {
        for (int i = 1; i < m; i++) {
            if (!(it != s.end())) {
                it = s.begin();
            }
            it++;
        }
        if (!(it != s.end())) {
            it = s.begin();
        }
        
        if (flag == 0) {
            cout << *it;
            flag = 1;
        }
        else {
            cout <<" "<< *it;
        }
            
        int c = *it;
        s.erase(c);
        int j = 1;
        while (1) {
            it = s.find((c + j) % n);
            if (it != s.end())
                break;
            else
                j++;
            if (j == n) {
                break;
                it = s.end();
            }
        }
        
        if (!(it != s.end())) {
            it = s.begin();
        }
    }
}

得出结果:3 6 1 5 2 8 4 7

PTA提交结果:正确

同一个测试点两种代码给出的结果是不一样的,而PTA上提交都是正确的,说明测试点没有考虑到n远大于m的情况

posted @ 2019-04-18 21:09  海杰wrangle  阅读(825)  评论(2编辑  收藏  举报