这个C ++代码有什么问题?编程中的3n + 1 - 挑战/ UVa

时间:2012-06-23 03:03:22

标签: c++

Programming-Challenges网站将其标记为错误答案。我检查了样品输入,它们都是正确的。我在代码中添加了一个优化,我做了它,因此它不会检查已知在另一个数字序列中的数字,因为它将是一个子序列,显然具有更短的循环长度。

此外,我刚回到编程中,所以程序不是太简洁,但我希望它是可读的。

以下是代码:

#include <iostream>
#inclue <vector>
struct record
{
   int number;
   int cyclelength;
};

void GetOutput(int BEGIN, int END)
{
    //determines the output order at the end of function
    bool reversed = false;
    if (BEGIN > END)
    {
        reversed = true;
        int temp = BEGIN;
        BEGIN = END;
        END = temp;
    }
    vector<record> records;
    for (int i = BEGIN; i <= END; ++i)
    {
        //record to be added to records
        record r;
        r.number = i;
        r.cyclelength = 1;
        records.push_back(r);
    }

    int maxCycleLength = 1;
    //Determine cycle length of each number, and get the maximum cycle length
    for (int i =0;i != records.size(); ++i)
    {
        //
        record curRecord = records[i];
        //ABCD: If a number is in another number's sequence, it has a lower cycle length and do not need to be calculated,
        //set its cyclelength to 0 to mark that it can be skipped
        if (curRecord.cyclelength != 0)
        {
            //
            while (curRecord.number != 1)
            {
                //next number in the sequence
                int nextNumber;
                //finds the next number
                if (curRecord.number % 2 == 0)
                    nextNumber = curRecord.number / 2;
                else
                {
                    nextNumber = curRecord.number * 3 + 1;
                    //if nextNumber is within bounds of input, mark that number as skippable; see ABCD
                    if (nextNumber <= END)
                    {
                        records[nextNumber - BEGIN].cyclelength = 0;
                    }
                }
                curRecord.number = nextNumber;
                curRecord.cyclelength += 1;
            }
            maxCycleLength = max(curRecord.cyclelength, maxCycleLength);
        }
    }
    if (reversed)
    {
        cout << END << " " << BEGIN << " " << maxCycleLength;
    }
    else
    {
        cout << BEGIN << " " << END << " " << maxCycleLength;
    }
}

int main(){
    //The first and last numbers
    vector< vector<int> > input;
    int begin, end;

    while (cin >> begin >> end)
    {
        //storage for line of input
        vector<int> i;
        i.push_back(begin);
        i.push_back(end);
        input.push_back(i);
    }


    for (int i = 0;i != input.size(); ++i)
    {
        GetOutput(input[i][0], input[i][1]);
        cout << endl;
    }

    return 0;
}

2 个答案:

答案 0 :(得分:2)

我会试着给你一个提示,让你弄清楚问题。

样本输入可以作为冒烟测试,但它们通常不是您的程序可以处理更极端测试用例的好指标。您应该始终使用多个示例输入进行测试。如果我的计算是正确的,那么您的程序将产生以下输入的错误结果:

999000 999250

作为参考,此预期输出为:

999000 999250 321 

在那里,我将搜索空间缩小到251个周期:)现在让你的调试器完成工作。

无论如何,以下是扰流标记的完整解释和解决方案。如果你想阅读它,请将鼠标悬停在空白处,如果你想自己想象,请保持原样。

  

问题表明i和j小于一百万,并且没有操作溢出32位整数。这意味着没有中间结果会大于4294967295.但是,int是有符号类型,因此,即使它有32位,它只有31位的绝对值,因此不能适合任何大于2147483647的数字。大于这些的数字出现在问题范围内的几个N的循环中,其中一个是999167.使用无符号的32位整数是一种解决方案。

答案 1 :(得分:1)

没有什么神秘之处。最大的中间数溢出了有符号整数的31位。您需要将record.numbernextNumber声明为unsigned int