从 num1 到 num2 的最短路径(以 C++ 为单位)

The shortest way from num1 to num2 (in C++)

本文关键字:C++ 为单位 最短路径 num1 num2      更新时间:2023-10-16

我需要编写一个函数(C++),它得到两个整数(>0)(n1,n2)。我只能做两件事:

  • 将 1 添加到 N1。
  • 将 n1 乘以 2。

该函数返回从 n1 到 n2 的最短步数。你能给我一些想法吗?

谢谢!

附言如果不可能,则函数返回 -1。

在这里我尝试过:

if (n1<n2)
{
    n1++;
    if ((n1)*2<=n2)
        return 2+f(n1*2,n2);
    else
        return 1+f(n1,n2);
}
我想最好

扭转问题:从 n2 到 n1 使用以下两个 ting:

  • 减去 1
  • 除以 2(仅当结果为整数时)

这样,当您第一次尝试将数字除以 2 时,您就可以找到最大的步骤,如果不可能,则减去 1(之后除法有效)。继续这样做,直到你达到n1(或更低的值,之后你只能使用"减少步骤",因此基本上已经知道所需的步骤数)

我想你可以自己实现这个算法...

一步

一步地考虑一下。

假设n1startn2end

如果您已经在end,那么您不需要任何步骤。如果start大于end,则无法做到这一点。

否则你有两个选择..

  • 将 1 添加到start并递归重复该过程 - 将步骤数存储为add
  • start乘以 2 并递归重复该过程 - 将步骤数存储为mult

如果两者都有可能,那么两者中最低的就是你的答案。

如果你在删除我的代码之前得到了它,我希望你能花时间逐步完成它,否则你可以尝试把它写出来。大约需要一分钟左右。

附言对于大量步骤,您可能希望将其实现为尾递归算法以防止<insert name of the website here>

p.p.s 这是一个非常低效的算法,因为它探索每个分支。您可以尝试改进它并尝试减少所需的分支数量,也许只有在 mult 不起作用时才添加。

如前所述,你可以通过将问题转化为一个承认贪婪选择的问题,从 n2 到 n1 反向。答案当然是一样的。

但可以做更多的观察:

  • 如果换档会导致数字太低,则从现在开始必须采取的步骤数是current - n1,您不必一一计算所有这些步骤。
  • 如果移位
  • 会导致一个不太低的数字,无论你目前是奇数还是偶数,你总是可以移位(但将最低位添加到所采取的步数中,因为它会采取一步)
  • 使用 N1 和 N2 中最高设置位的位置,可以一次执行多个班次(将移出的位的移位量和汉明重量添加到步数中)。您可以执行的班次数是bsr(n2) - bsr(n1) - 1,但要注意边缘情况。这并不总是最大班次步骤数,它可以多花一个(但不超过这个步骤)。
int numOfSteps(int n1, int n2) {
    if (n1 > n2) return -1;
    if (n1 == n2) return 0;
    int result = 0;
    while (n1 * 2 <= n2) {
            n1 *= 2;
            result ++;
    }
    while (n1 < n2) {
            n1 ++;
            result ++;
    }
    return result;
}

我解决了!(我向我的朋友征求建议...

这是代码:

int f(unsigned int n1, unsigned int n2){
int num1,num2;
if (n1==n2)
        return 0;
if (n1>n2)
    return -1;
num1=f(n1+1,n2)+1;
num2=f(n1*2,n2)+1;
return min(num1,num2);}

这是"分钟":

int min (unsigned int n1, unsigned int n2){
if (n1*n2==0) //If one of them is zero then (n1+n2) return the non-zero
              //number.
    return n1+n2;
else
    if (n1>n2)
        return n2;
    else
        return n1;}

谢谢!!