解决难题(最佳解决方案)
Resolving a puzzle (optimal solution)
我有一个 3x3 数字的谜题如下:
3 | 5 | 2
7 | 8 | 9
1 | 6 | 4
作为解决方案:
1 | 2 | 3
4 | 5 | 6
7 | 8 | 9
规则是我只能移动附近的"碎片",直到我得到解决方案。
我对此的看法是计算偏移量,然后将其运行到"花哨"算法中以获得有效的解决方案。但是,我只能想到使用蛮力并检查程序为找到最有效的步骤所做的步骤数量。
在偏移中,我的意思是:
(2, 0) | (0, 1) | (-1, 0)
(0, 1) | (0, 1) | ( 0, 1)
(0, -2) | (1, -1) | (-2, -1)
哪些是笛卡尔计划中 x 和 y 的偏移量。我得到了以下内容,它确实计算了偏移量,但没有关于"花哨算法"的想法。
https://ideone.com/0RP83x
有没有一种有效的方法可以在不使用蛮力的情况下获得解决方案的最小动作?
可以将网格视为节点(图形的一部分(。
让我们编写网格
abc
def
ghi
作为单行abcdefghi
.
您从节点352789164
开始,想要到达节点123456789
。
节点的邻居是您可以通过应用交换到达的所有节点。 例如123456789
对邻居有
[
213456789, 132456789,
123546789, 123465789,
123456879, 123456798,
423156789, 153426789,
126453789, 123756489,
123486759, 123459786
]
然后,您可以通过提供以下内容来申请 A*:
d(nodeA, nodeB) = weight(nodeA, nodeB) = 1
(所有掉期费用为1(h(node)
= 获得解决方案所需的最少交换次数。
要获得最小的h
,请考虑计算错位的数字。
- 如果您有偶数个错位的数字,则至少需要"一半"的交换
- 如果您有奇数个错位的数字,那么一半 + 1(例如,目标 123 的 312 需要 2 次交换(
下面的js示例,我从wiki复制粘贴的代码
function h (node) {
const s = ''+node
let misplaced = 0
for(let i = 0; i < s.length; ++i) {
if (parseInt(s[i]) != i+1) {
misplaced++
}
}
if (misplaced % 2 === 0) {
return misplaced / 2
}
return Math.ceil(misplaced / 2)
}
function d (a, b) {
return 1
}
const swaps = (_ => {
const arr = [[1,2],[2,3],[4,5],[5,6],[7,8],[8,9],[1,4],[2,5],[3,6],[4,7],[5,8],[6,9]]
function makePermFunc([a,b]) {
a--
b--
return function (node) {
const s = (''+node)
const da = parseInt(s[a])
const db = parseInt(s[b])
const powa = 9 - a - 1
const powb = 9 - b - 1
node -= da * 10**powa
node -= db * 10**powb
node += da * 10**powb
node += db * 10**powa
return node
}
}
const funcs = arr.map(makePermFunc)
return node => funcs.map(f => f(node))
})();
//https://en.wikipedia.org/wiki/A*_search_algorithm
function reconstruct_path (cameFrom, current) {
const total_path = [current]
while(cameFrom.has(current)) {
current = cameFrom.get(current)
total_path.unshift(current)
}
return total_path
}
// A* finds a path from start to goal.
// h is the heuristic function. h(n) estimates the cost to reach goal from node n.
function A_Star(start, goal, h) {
// The set of discovered nodes that may need to be (re-)expanded.
// Initially, only the start node is known.
const openSet = new Set([start])
// For node n, cameFrom[n] is the node immediately preceding it on the cheapest path from start to n currently known.
const cameFrom = new Map()
// For node n, gScore[n] is the cost of the cheapest path from start to n currently known.
const gScore = new Map()
gScore.set(start, 0)
// For node n, fScore[n] := gScore[n] + h(n).
const fScore = new Map()
fScore.set(start, h(start))
while (openSet.size) {
//current := the node in openSet having the lowest fScore[] value
let current
let bestScore = Number.MAX_SAFE_INTEGER
for (let node of openSet) {
const score = fScore.get(node)
if (score < bestScore) {
bestScore = score
current = node
}
}
if (current == goal) {
return reconstruct_path(cameFrom, current)
}
openSet.delete(current)
swaps(current).forEach(neighbor => {
// d(current,neighbor) is the weight of the edge from current to neighbor
// tentative_gScore is the distance from start to the neighbor through current
const tentative_gScore = gScore.get(current) + d(current, neighbor)
if (!gScore.has(neighbor) || tentative_gScore < gScore.get(neighbor)) {
// This path to neighbor is better than any previous one. Record it!
cameFrom.set(neighbor, current)
gScore.set(neighbor, tentative_gScore)
fScore.set(neighbor, gScore.get(neighbor) + h(neighbor))
if (!openSet.has(neighbor)){
openSet.add(neighbor)
}
}
})
}
// Open set is empty but goal was never reached
return false
}
console.log(A_Star(352789164, 123456789, h).map(x=>(''+x).split(/(...)/).filter(x=>x).join('n')).join('n----n'))
console.log('a more basic one: ', A_Star(123654987, 123456789, h))
相关文章:
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- 解决难题(最佳解决方案)
- 比较/搜索数组中多个整数的最佳解决方案
- 找出迷宫求解器的最佳解决方案,并具有动画输出
- 从QTcpSocket上的数据流中连续运行复杂算法的最佳Qt线程解决方案是什么
- CPLEX 如何以相同的成本获得所有不同的最佳解决方案
- 我该如何判断k-server动态解决方案的最佳路径以数组成本[i] [j] [k] [t]位于何处
- 暂停和恢复线程的最佳解决方案是什么?
- 需要包含运行任务时间的 2D 矩阵的最佳解决方案
- 为什么通过系统("color YX")更改控制台应用程序中C++颜色不是最佳解决方案?
- 查找内存泄漏的最佳解决方案
- 在c++中绘制(原语,线条等)的最佳通用跨平台解决方案
- LTO优化负面影响并找到最佳解决方案