【发布时间】:2021-11-23 02:52:42
【问题描述】:
我有一种情况,我需要根据一些成本在数组中找到最佳拆分位置。问题是这样的:
作为输入,我有一个按整数时间戳排序的事件数组,作为输出,我想要一个索引数组,它将输入数组分成许多部分。输出数组需要是最优的(下面会详细介绍)。
struct e {
int Time;
// other values
}
Example Input: [e0, e1, e2, e3, e4, e5, ..., e10]
Example output: [0, 2, 6, 8] (the 0 at the start is always there)
使用上述示例,我可以使用拆分索引将原始数组划分为 5 个子数组,如下所示:
[ [], [e0, e1], [e2, e3, e4, e5], [e6, e7], [e8, e9, e10] ]
这个示例解决方案的成本是子数组之间“距离”的总成本:
double distance(e[] arr1, e[] arr2) {
// return distance from arr1 to arr2, order matters so non-euclidean
}
total cost = distance([], [e0, e1]) + distance([e0, e1], [e2, e3, e4, e5]) + ...
此时有助于理解实际问题。
输入数组表示某个时间的音符(即 MIDI 文件),我想将 MIDI 文件拆分为最佳吉他指法。因此,每个音符子阵列代表一个和弦(或在单个指法中组合在一起的旋律)。两个子阵列之间的距离表示从一种指法模式移动到另一种指法模式的难度。目标是找到用吉他弹奏歌曲的最简单(最佳)方式。
我还没有证明它,但对我来说,这看起来像是一个 NP-Complete 或 NP-Hard 问题。因此,如果我可以将其简化为另一个已知问题并使用已知的分治算法,这可能会有所帮助。此外,可以使用更传统的搜索算法(A* ?)来解决这个问题。它可能是有效的,因为我们可以比在常规图中更快地过滤掉错误的解决方案(因为从技术上讲,输入是一个完整的图,因为每个指法都可以从任何其他指法到达)。
我无法决定最好的方法是什么,所以我目前陷入困境。任何提示或想法将不胜感激。
【问题讨论】:
-
有没有规定第一个子数组总是
[],或者某些子数组是不允许的,或者你需要最小子数组数?更具体地说,是什么阻止您获取整个阵列? -
@kcsquared 是的,第一个子数组总是空的,因为在播放一首歌曲时,您从没有手指在任何琴弦上开始。当且仅当歌曲包含最多 6 个不同的音符并且它们可以同时播放时,从技术上讲,整个数组可以被取出。不过,这可能永远不会发生在任何真正的歌曲中。
标签: algorithm search midi dijkstra