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故障。但是,我想知道,那么我应该如何为此做出逻辑呢?这将是什么递归函数?谢谢!
答案 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并将其传入,这样您就不必每次都重新计算。