为什么我对3n + 1拼图的解决方案被拒绝了?

时间:2015-09-19 05:39:36

标签: c++ algorithm recursion memoization

我正在尝试解决UVa在线评判的算法问题,但我被困在3n+1 problem上。我每次都看到正确的输出,但法官说这是一个错误的答案。为什么呢?

另外,如何优化此代码,以便1000000不需要很长时间?

#include <iostream>
#include <string>
#include <stdio.h>

using namespace std;

int main(){
    int a;


 int b;
    int cyclelength(int i);
     while (scanf("%d %d\n",&a,&b)==2){

    int max = 0;

   if (b < a){
        for (int i = b; i < a; i++){
        if (cyclelength(i) > max)
            max = cyclelength(i);
             }
   }

   else    
   {
        for (int i = a; i < b; i++){
             if (cyclelength(i) > max)
                  max = cyclelength(i);
         }
   }


    cout << a << " " << b << " " << max << endl;

    }
}

int cyclelength(int i){
    if(i==1)
        return 1;


    if(!(i%2))
         return cyclelength(i/2)+1;
     else
        return cyclelength(3*i+1)+1;
     }

1 个答案:

答案 0 :(得分:0)

您提交的内容不正确,因为您没有在ab范围内进行迭代。

问题陈述如下:

  

对于每对输入整数 i j ,您应输出 i j ,并且最大值 i j 之间和之间的整数的循环长度。

您的代码循环

for (int i = b; i < a; i++)

for (int i = a; i < b; i++)

因此在前一种情况下省略a,在后一种情况下省略b

您应该将循环更改为

for (int i = b; i <= a; i++)

for (int i = a; i <= b; i++)

您可以memoizing cyclelength的结果稍微加快您的代码速度。这使您可以查找以前计算的值,而不是花时间再次计算它们。

以下是cyclelength的备忘版本:

#include <map>
using namespace std;

map<long long, int> memo;

int cyclelength(long long i) {
  if (i == 1) {
    return 1;
  } 

  if (memo.count(i) == 1) {
    return memo[i];
  }

  if (i%2 == 0) { 
    return memo[i] = 1 + cyclelength(i/2);
  } else { 
    return memo[i] = 1 + cyclelength(3*i + 1);
  } 
}

unordered_map会更快,但UVA判断为#include <unordered_map>返回了编译错误。

请注意,我的cyclelength版本采用long long参数。这让我可以计算cyclelength(999999),如果你将自己限制在32位整数值,最终会因重复的3n + 1操作而导致整数溢出。问题陈述承诺“没有操作溢出32位整数”,如果只使用int值,则可以接受提交,但如果要计算{{1,则必须使用更大的整数类型对于范围[1,1000000)中的值。