我的逻辑出错了哪里涉及乘以2并减1以获得给定的数字?

时间:2015-11-09 18:39:38

标签: algorithm recursion

http://codeforces.com/contest/520/problem/B

Vasya找到了一个奇怪的设备。在设备的前面板上有:红色按钮,蓝色按钮和显示正整数的显示。单击红色按钮后,设备将显示的数字乘以2。单击蓝色按钮后,设备会从显示屏上的数字中减去一个。如果在某个时刻该数字停止为正数,则设备会发生故障。显示器可以显示任意大的数字。最初,显示屏显示数字n。

鲍勃希望在显示屏上显示数字m。为了达到这个结果,他必须达到的最小点击次数是什么?

输入 输入的第一行和唯一一行包含两个不同的整数n和m(1≤n,m≤10^ 4),用空格分隔。

输出 打印一个数字 - 需要按下按钮才能获得数字m的数量n的最小次数。

我开发了以下递归解决方案。我知道它会超时,但我会记住它,这将使我的解决方案得到接受。但截至目前,我在其中一个输入中得到了错误的答案。

我的代码是:

int func (int n, int m);
int main (void)
{
    int n,m;
    cin>>n>>m;
    int count = func(n,m);
    cout<<count<<"\n";
    return 0;
}

int func (int n, int m)
{
    if (n == 0)
        return INT_MAX; // this should be because we can never go to some 
                        // other digit if we are at 0
    if (n == m)
        return 0;
    else if (2*n == m || n == m+1)
        return 1;
    else if (n > m)
        return func(n-1,m)+1;
    else 
        return min(func(n-1,m),func(n*2,m))+1;
}

现在,当我输入(1,3)输入时,我的代码显示了Segmentation fault。我试着调试它,我发现它有一种无限循环,因为我得到了Seg故障。但是,我想知道,那么我应该如何为此做出逻辑呢?这将是什么递归函数?谢谢!

1 个答案:

答案 0 :(得分:3)

SEG故障是由于计算INT_MAX + 1。

实际上我觉得这个问题可以通过这种方式更好地解决。

  • 对于所有情况n> m,最短计数为n-m。

    Application aaa bbbb
    
  • 对于所有情况n == m,最短计数为0.

    if (n<m)
        return n-m;
    
  • 对于所有情况,n&lt; m,最短计数可以计算为:

    else if (n==m)
        return 0;
    

对于n = 57,m = 201,则Y = [101,51,26,13,7,4,2,1],X为51。 所以答案可以计算为

let sequence Y= [(m/(2^1), m/(2^2), ... 1]  // use the ceiling values
find X is the next number in the Y where n >= X.
return func(X*2) + n-X + 1;

对于n = 4,m = 6,则Y = [3,2,1],X将为3。 所以答案可以计算为

 (57-51)+1 = 7 steps, result now 51*2 = 102
 (102-101)+1 = 2 steps, result now 101*2 = 202
 (202-201) = 1 steps
 =====> Total steps 10

对于n = 1,m = 3,则Y = [2,1],X将为1。 所以答案可以计算为

 (4-3)+1 = 2 steps, result now 3*2=6
 =====> Total steps 2

请注意,您可以在输入功能之前预先计算Y并将其传入,这样您就不必每次都重新计算。