虽然测试用例是正确的,但UVA的3n + 1错误答案。 。 。?

时间:2012-03-08 21:05:39

标签: c

UVA problem 100 - The 3n + 1 problem

我已经尝试过所有测试用例,没有发现任何问题。 我检查的测试用例:

  • 1 10 20
  • 100 200 125
  • 201 210 89
  • 900 1000 174
  • 1000 900 174
  • 999999 999990 259

但为什么我一直都会错误回答?

这是我的代码:

#include "stdio.h"

unsigned long int cycle = 0, final = 0;

unsigned long int calculate(unsigned long int n)
{
    if (n == 1)
    {
        return cycle + 1;
    }
    else
    {
        if (n % 2 == 0)
        {
            n = n / 2;
            cycle = cycle + 1;
            calculate(n);
        }
        else
        {
            n = 3 * n;
            n = n + 1;
            cycle = cycle+1;
            calculate(n);
        }
    }
}


int main()
{
    unsigned long int i = 0, j = 0, loop = 0;
    while(scanf("%ld %ld", &i, &j) != EOF)
    {
        if (i > j)
        {
            unsigned long int t = i;
            i = j;
            j = t;
        }
        for (loop = i; loop <= j; loop++)
        {
            cycle = 0;
            cycle = calculate(loop);

            if(cycle > final)
            {
                final = cycle;
            }
        }
        printf("%ld %ld %ld\n", i, j, final);
        final = 0;
    }
    return 0;
}

5 个答案:

答案 0 :(得分:5)

线索是你收到 i j 但是它没有说i&lt; j适用于所有情况,请在代码中检查该条件并记住始终按顺序打印:

<i>[space]<j>[space]<count>

答案 1 :(得分:2)

如果输入“乱序”,您可以交换数字,即使在输出中,当明确说明您应该保留输入顺序时。

答案 2 :(得分:1)

看不出你的测试用例是如何实际工作的;你的递归案例永远不会返回任何内容。

答案 3 :(得分:0)

第1部分

这是冰雹序列,对吗?你试图从给定的N开始确定冰雹序列的长度。你知道,你真的应该拿出那个丑陋的全局变量。递归计算它是微不足道的:

long int hailstone_sequence_length(long int n)
{
  if (n == 1) {
    return 1;
  } else if (n % 2 == 0) {
    return hailstone_sequence_length(n / 2) + 1;
  } else {
    return hailstone_sequence_length(3*n + 1) + 1;
  }
}

注意循环变量是如何消失的。这是不必要的,因为每次调用只需要为递归调用计算的值加1。递归最低点为1,因此我们将其计为1.所有其他递归步骤都加1,所以最后我们留下序列长度。

注意:此方法需要与输入n成比例的堆栈深度。

我放弃使用unsigned,因为这对于做大多数数学来说是不合适的类型。从(无符号长整数)0中减去1时,会得到一个大于2的幂的正数。在大多数情况下,这不是一种理智的行为(但在少数情况下恰好是正确的行为)。

现在让我们讨论你哪里出错了。您的原始代码会尝试通过修改名为cycle的全局计数器来测量hailstone序列长度。但是,main函数需要calculate返回一个值:您有cycle = calculate(...)

问题是你的两个案子没有返回任何东西!从未返回任何内容的函数中提取返回值是未定义的行为。

(n == 1)案例确实返回了一些内容,但它也有一个错误:它无法增加cycle;它只返回cycle + 1,使循环保留原始值。

第2部分

看着主力。让我们重新格式化一下。

int main()
{
  unsigned long int i=0,j=0,loop=0;

将这些更改为long。顺便说一下,scanf中的%ld期望长,而不是无符号长。

  while (scanf("%ld %ld",&i,&j) != EOF)

小心scanf:它的返回值多于EOF。如果无法进行转换,Scanf将返回EOF。如果它能够扫描一个数字而不是第二个数字,它将返回1.基本上,这里更好的测试是!= 2。如果scanf没有返回2,则输入出错。

  {
    if(i > j)
    {
      unsigned long int t=i;i=j;j=t;
    }
    for(loop=i;loop<=j;loop++)
    {
      cycle=0;
      cycle=calculate(loop );

      if(cycle>final)
      { 
        final=cycle;
      } 
    }

计算现在称为hailstone_sequence_length,因此该块可以只有一个局部变量:{ long len = hailstone_sequence_length(loop); if (len > final) final = len; }

也许final应该被称为max_length

    printf("%ld %ld %ld\n",i,j,final);
    final=0;

final应该是此循环中的局部变量,因为它分别用于每个测试用例。然后你不必记得把它设置为0。

  }
  return 0;
}

答案 4 :(得分:0)

这是一个仅供参考的单行班次

int three_n_plus_1(int n)
{
    return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}

不太确定你的代码如何在你计算它之后立即“循环”,因为'calculate'对于它的许多情况没有明确的返回值(你应该有编译器警告这个效果)。如果你没有循环=循环=计算(那么它可能会起作用吗?

并将它们捆绑在一起: -

int three_n_plus_1(int n)
{
    return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}

int max_int(int a, int b) { return (a > b) ? a : b; }
int min_int(int a, int b) { return (a < b) ? a : b; }

int main(int argc, char* argv[])
{   
    int i,j;
    while(scanf("%d %d",&i, &j) == 2)
    {
        int value, largest_cycle = 0, last = max_int(i,j);
        for(value = min_int(i,j); value <= last; value++) largest_cycle = max_int(largest_cycle, three_n_plus_1(value));
        printf("%d %d %d\r\n",i, j, largest_cycle);
    }   
}