Algorithm 通过加或减两个整数之间的最短路径
以下是此问题的描述: 给你两个整数a和b。您希望找到将a转换为b所需的最短操作序列,在每个步骤中,您可以添加或减去5、7或12 例如,如果给定a=-5和b=19,则最短路径为Algorithm 通过加或减两个整数之间的最短路径,algorithm,math,numbers,theory,equation,Algorithm,Math,Numbers,Theory,Equation,以下是此问题的描述: 给你两个整数a和b。您希望找到将a转换为b所需的最短操作序列,在每个步骤中,您可以添加或减去5、7或12 例如,如果给定a=-5和b=19,则最短路径为 -5 + 12 + 12 = 19 如果给定1和3,则最短路径为 1 + 7 - 5 = 2 我能想到的解决这个问题的唯一方法就是使用BFS,也许还有更多的修剪。有没有更好的算法可以替代 谢谢 我想你可以看一下电话号码来寻找想法。这个问题相当于获取a-b的号码。或者abs(a-b),因为它是围绕零对称的。我认为这可以很
-5 + 12 + 12 = 19
如果给定1和3,则最短路径为
1 + 7 - 5 = 2
我能想到的解决这个问题的唯一方法就是使用BFS,也许还有更多的修剪。有没有更好的算法可以替代
谢谢 我想你可以看一下电话号码来寻找想法。这个问题相当于获取a-b的号码。或者
abs(a-b)
,因为它是围绕零对称的。我认为这可以很容易地通过采用。例如,获取23的最快方法是获取23+5,23-5,23+7,23-7,23+12
或23-12
加上一个操作的最快方法。如果你在开始条件下应用几次(成本+5,-5,…是1,其他的是无限的),你将在O(a-b)
中得到你的答案,你需要解5x+7y+12z=b-a。使得| x |+| y |+| z |最小。也许有一种简单的数学方法。也许这会有所帮助:让我们从一组有趣的观察开始。正如许多其他人所指出的,目标是找到一些具有整数系数的5x+7y+12z=b-a的线性组合,以使| x |+| y |+| z |最小化。但我们可以利用这三个数字之间的一些非常有趣的联系:
- 5x+7y=b-a
- 5x+12z=b-a
- 7y+12z=b-a
Let best = infinity
# Solve 5x + 7y = b - a
for x = -6 to +6:
if ((b - a) - 5 * x) mod 7 = 0:
best = min(best, |x| + |((b - a) - 5 * x) / 7|)
# Solve 5x + 12y = b - a
for x = -11 to +11:
if ((b - a) - 5 * x) mod 12 = 0:
best = min(best, |x| + |((b - a) - 5 * x) / 12|)
# Solve 7x + 12y = b - a
for x = -11 to +11:
if ((b - a) - 7 * x) mod 12 = 0:
best = min(best, |x| + |((b - a) - 7 * x) / 12|)
return best;
该算法速度惊人——它只需O(1)个时间,因为求解每三个线性系统所需的迭代次数是一个常数(最多23次)。它只需要O(1)个内存来保存可能的值,我认为在实践中,它可能是您能够编写的最快的算法
希望这有帮助 将所有操作组合预先计算成一个哈希映射,然后只需查找答案 预计算步骤需要时间,但一旦完成,您将在预计算范围内找到答案,即1查找操作 下面是一个小的JavaScript演示:
// maximum depth of combos to try
var MAX = 6;
// possible operations
var ops = ["+-5", "+5", "+-7", "+7", "+-12", "+12"];
// initial hash map of operations->value
var all = {"+5":5, "+-5":-5, "+7":7, "+-7":-7, "+12":12, "+-12":-12};
var allcnt = 6; // count combos *not needed*
// initial hash map of values->operations, plus "0" so we can avoid it
var unique = {"0": "0", "5":"+5", "-5":"+-5", "7":"+7", "-7":"+-7", "12":"+12", "-12":"+-12" };
var ready = false;
// get all useful combinations of ops
function precalc() {
var items = [];
for(var p in all) {
items.push(p);
}
for(var p=0; p<items.length; p++) {
for(var i=0; i<ops.length; i++) {
var k = items[p] + ops[i];
var v = eval(k);
if(unique[v] == null) {
unique[v] = k;
all[k] = v;
allcnt++;
}
}
}
}
// find an answer within the pre-calc'd depth
function find(a, b) {
if(ready === false) {
for(var i=0; i<MAX; i++) precalc();
ready = true;
}
return unique[""+Math.abs(a-b)];
}
// test
find(-5,19);
//要尝试的组合的最大深度
var MAX=6;
//可能的操作
变量运算=[“+-5”、“+5”、“+-7”、“+7”、“+-12”、“+12”];
//操作的初始哈希映射->值
var all={“+5”:5,“+-5”:-5,“+7”:7,“+-7”:-7,“+12”:12,“+-12”:-12};
var allcnt=6;//计数组合*不需要*
//值->操作的初始哈希映射,加上“0”,这样我们就可以避免它
var unique={“0”:“0”、“5”:“+5”、“-5”:“+-5”、“7”:“+7”、“-7”:“+-7”、“12”:“+12”、“-12”:“+-12”};
var ready=false;
//获取所有有用的操作组合
函数precalc(){
var项目=[];
用于(var p总计){
推送(p);
}
对于(var p=0;p预先计算第一个最小范围所需的运算,然后继续添加+12的倍数。是