我正试图用c#
来解决这个问题使用自然数,可以使用以下过程:
在给定数字的右侧键入0 在给定数字的右侧键入4号 将数字除以2
如果给出第55号,可以获得以下数字:2003,2004,2005,2006,2007
(((((如果我们获得32号,那么我们可以获得这些数字中的任何一个:2003,2004,2005,2006,2007)))
我们可以通过28个步骤找到解决方案。
所以我写了这段代码:
static void Main(string[] args)
{
long number = 550, goal = 32;
int count = 0;
bool flag = false;
find(number, goal, count, flag);
Console.WriteLine("Done");
Console.ReadKey();
}
static bool find(long number, long goal, int count, bool flag)
{
if(number==goal) { Console.WriteLine(number); return true; }
if(count ==28 && number != goal) { return false;}
else
{
flag =find(number*10, goal, count+1, flag);
if (flag == true) { Console.WriteLine(number); return flag; }
flag = find(number * 10 + 4, goal, count + 1, flag);
if (flag == true) { Console.WriteLine(number); return flag; }
if (number % 2 == 0) {
flag= find(number / 2, goal, count + 1, flag);
if (flag == true) { Console.WriteLine(number); return flag;
} }
return flag;
}
}
任何人都可以加速递归进度
答案 0 :(得分:0)
您的实施很简单,但很天真。它会经历所有可能性,直到找到匹配为止。经过一番思考,你实际上可以淘汰大部分计算。
当您的递归代码执行时,每个递归调用分成3个路径,使其最多为 3 ^ 28 不同的可能性。这是最糟糕的情况,当方法的结果是错误的。一旦找到第一条路径,您的代码就会解析,但很有可能会浪费大量时间进行必要的计算。
我将以你的数字为例,所以我可以说清楚:
假设我进行以下调用:find(550,32,0,false);
在某个时间点,您的程序将沿着它的路径前进 将不断乘以550乘以10.但为什么要将它乘以10 如果32小于550?
在另一个时间点,您的程序将沿着它的路径前进 将乘以550乘以10并连续加4。但和以前一样,为什么呢 当目标较小时继续上升?
所以这是最后的结论:
设数字 =传递给参数的当前值,数字。
让 remIteration =剩余的递归调用次数。 (28 - 当前递归调用#)
让 maxDivisor = 2 ^ x。这是当前值可以除以的最大值。
让 smallestFuture = number / maxDivisor。
基本上, smallestFuture 是来自的最小可能值 当前的递归调用。它是通过不断划分来计算的 当前数字2,直到递归计数达到28.然后,如果 smallestFuture 仍然大于目标号码,会有 没有必要计算当前路径下的计算。
以下是我写的代码。函数调用被修改,因为我认为使用flag参数没有意义。如果您愿意,请随意添加。
static bool find(long number, long goal, int count)
{
if (number == goal)
{
Console.WriteLine(number);
return true;
}
if (count == 28 && number != goal)
return false;
int remIteration = 28 - count;
long maxDivisor = (long)Math.Pow(2, remIteration);
long smallestFuture = number / maxDivisor;
if (smallestFuture > goal)
return false;
if (smallestFuture == goal)
{
Console.WriteLine(number);
return true;
}
long newNumber = number * 10;
int nexCount = count + 1;
if (find(newNumber, goal, nexCount) || find(newNumber + 4, goal, nexCount))
{
Console.WriteLine(number);
return true;
}
if (number % 2 == 0)
{
if (find(number / 2, goal, nexCount))
{
Console.WriteLine(number);
return true;
}
}
return false;
}
不幸的是,我现在没有足够的时间使用dynamic programming来解决这个问题,但它肯定会提供比我的代码更好的性能。请注意,我的代码与您的代码非常相似,会打印出它检测到的第一个可能的路径,而不是最佳路径。