我有一个难以解决的问题(至少我是怎么看的)。我有一个 die (面对1到6)有不同的值(除了[1-6]以外)和板(n-by-m)。我有一个起始位置和一个完成位置。我可以通过滚动模具从一个正方形移动到另一个正方形。通过这样做,我必须将顶面添加到总和/成本。
现在我必须计算如何从开始位置到最终位置的最小值 总和/成本。我已经尝试了几乎所有的东西,但我无法找到正确的算法。
我尝试了Dijkstra,但它没用,因为在正确的路径中有一些中间节点 我可以从另一条路径获得更好的总和(最终证明是不正确的)。我该如何更改算法?
算法概述:
dijkstra:PriorityQueue
if(我可以到达一个总和较小的节点)
,将其从队列中删除,
我改变了它的成本和模具位置
,将其添加到队列中。
这是代码:
public void updateSums() {
PriorityQueue<Pair> q = new PriorityQueue<>(1, new PairComparator());
Help h = new Help();
q.add(new Pair(startLine, startColumn, sums[startLine][startColumn]));
while (!q.isEmpty()) {
Pair current = q.poll();
ArrayList<Pair> neigh = h.getNeighbours(current, table, lines, columns);
table[current.line][current.column].visit(); //table ->matrix with Nodes
for (Pair a : neigh) {
int alt = sums[current.line][current.column] + table[current.line][current.column].die.roll(a.direction);
if (sums[a.line][a.column] > alt) {
q.remove(new Pair(a.line, a.column, sums[a.line][a.column]));
sums[a.line][a.column] = alt; //sums -> matrix with costs
table[a.line][a.column].die.setDie(table[current.line][current.column].die, a.direction);
q.add(new Pair(a.line, a.column, sums[a.line][a.column]));
}
}
}
}
答案 0 :(得分:3)
你还需要考虑Dijkstra状态下骰子的位置。
即。你不能只有sums[lines][column]
,你必须做sums[lines][column][die_config]
这样的事情,其中die_config
是你创建的一种方式,可以将骰子位置转换为整数。
例如,如果你的骰子最初看起来像这样:
^ 1&lt; 4 v2&gt; 9 f5 b7(^ =顶面,&lt; =左...下,右,前和 回)
int initial_die[6] = {1,4,2,9,5,7}
您可以通过简单地考虑指向向上的面部索引(从0到5)以及到向左的指数来将其转换为整数。这意味着你的骰子有少于36个(见底部注释)可能的旋转位置,你可以通过(从0开始) (up*6 + left)
之类的东西进行编码。我的意思是每个面都会有一个从0到5的值,无论它们与成本相关的值如何,所以按照上面的例子,我们将最初的顶面编码为索引0
,左边面对索引1
,等等。
所以具有配置值30
的骰子意味着left = 30%6 (=0)
最初指向的面(initial_die [0]),当前指向左侧,up = (30 - left)/6 (=5)
面部目前指向的是最初指向骰子的后退的那个(initial_die [5])。 所以这意味着骰子目前左侧的成本为1,顶部的成本为7 ,您可以从这些信息中获得骰子的其余部分,因为您知道最初的处置。 (基本上,这告诉我们模具向左侧滚动一次,然后向前滚动一次,与初始状态相比)
通过这些附加信息,您的Dijkstra将能够通过考虑到达最终节点的最便宜成本找到您寻找的正确答案,因为您可以拥有多个不同的最终模具位置。
注意:它实际上没有36个可能的位置,因为有些位置是不可能的,例如两个最初相对的侧面将无法在Up / Left上相邻。实际上只有24个有效位置,但我上面使用的简单编码实际上使用的索引最多可达~34,具体取决于你对芯片的编码方式。