假设我有一个目标号码n
,例如5,我总是从数字1开始,我必须*2
或*3
或+1
,直到我n
。所以在这种情况下,我会*2
两次,然后+1
得到5。
我应该找到达到目标值的最少操作次数。我看到类似的问题是posted,但这需要一定数量的步骤,而我必须找出最少的步骤。有关如何解决这个问题的提示吗?
这是一个家庭作业问题。
答案 0 :(得分:6)
可以将其视为搜索或 DP 问题(是的,实际上它们都与 状态转换相关 ),关键点是定义搜索状态条件,假设n
为正数,此处我们定义f[i] = inf, inf is a really large integer
表示数字i
无法访问,f[i] = k, k >= 0
表示数字{{ 1}}至少可以i
步骤到达。
如果k
不是那么大,我们可以使用数组来存储从1到n的每个数字的最小步数。最初是n
和f[1] = 0
。如果我们需要输出我们获取目标的方式(例如,输出5是f[i] = inf, 2 <= i <= n
),我们可以使用另一个数组1 2 4 5
来存储操作,定义pre
表示数字{{1数字由pre[i] = j
生成(例如,i
表示数字4由数字2生成,因为2 * 2 = 4; j
表示数字3由数字1生成,因为1 * 3 = 3):
pre[4] = 2
答案是pre[3] = 1
。
如何输出我们如何获得目标,我们使用 int inf = Integer.MAX_VALUE;
f[1] = 0;
pre[1] = -1; // pre[i] = -1 means i is the start point
for(i=2;i<=n;i++) {
f[i] = inf;
pre[i] = -1;
}
for(int i=1;i<=n;i++) { // since each number is positive so smaller number cannot be produced via larger number, no need to consider > n issue
if(f[i] == inf) {
continue;
}
if(2*i <= n && f[i] + 1 < f[2*i]) {
f[2*i] = f[i] + 1;
pre[2*i] = i; // means number 2*i is produced by number i
}
if(3*i <= n && f[i] + 1 < f[3*i]) {
f[3*i] = f[i] + 1;
pre[3*i] = i;
}
if(i+1 <= n && f[i] + 1 < f[i+1]) {
f[i+1] = f[i] + 1;
pre[i+1] = i;
}
}
数组来恢复操作:
f[n]
如果pre
非常大,您可能需要使用优先级队列来维护状态转换,并使用哈希集来维护每个数字的最小步骤。
答案 1 :(得分:2)
我认为前往这里的方法是向后工作。从someDivId
开始,尝试最大程度减少它的操作,然后尝试列表中的第二个等等。代码看起来像这样:
n
基本上,我们的想法是尽可能快地到达string actions = "";
int i = n, count = 0;
while (i > 1)
{
count++;
if (i % 3 == 0)
{
i = i / 3;
actions = "*3 " + actions;
continue;
}
if (i % 2 == 0)
{
i = i / 2;
actions = "*2 " + actions;
continue;
}
i--;
actions = "+1 " + actions;
}
。我不确定这是最少的步骤,但它似乎是一个良好的开端。
答案 2 :(得分:1)
您是否考虑过AI方法?
将问题视为树中的搜索:根是1,树中的每个节点X都有3个儿子:2 * X,3 * X,X + 1.
你可以构建整个树(每个节点X,其中X&gt; n不应该有更多的儿子)并使用BFS来找到从根到具有值n的节点的最短路径,或者如果图形不适合内存,请使用A*算法。
答案 3 :(得分:0)
这将为您提供有保障的最短路径。
static int result(int a, int b){
int answer = 0;
while (a < b){
if (b % 3 == 0 && b / 3 >= a){
b = b / 3;
answer++;
}
else if ((b - 1) % 3 == 0 && (b - 1) / 3 >= a){
b = b - 1;
b = b / 3;
answer += 2;
}
else if (b % 2 == 0 && b / 2 >= a){
b = b / 2;
answer++;
}
else{
b = b - 1;
answer++;
}
}
return answer;
}