1 回答
TA贡献1784条经验 获得超7个赞
您似乎试图通过将源列表加倍,然后通过重复切片和连接数组来打乱数字来找到最佳解决方案。
我认为这个问题适合递归方法。创建具有空槽的目标数组2 * len(list)。(槽是否为空必须用特殊值来标记,例如-1。)然后递归地尝试将原始数组的元素放入目标数组中。
让我们看一下您的示例 {0, 1, 3}。创建目标数组:
. . . . . .
尝试 0 的所有可能位置。第一个是
0 0 . . . .
现在尝试拟合1。有两种可能性
0 0 . . . .
0 0 1 . 1 .
但这无法容纳下一个元素, 3. 返回上一步:
0 0 . . . .
0 0 . 1 . 1
3个也不适合放在这里。我们已经用尽了对零位置的搜索,所以让我们采取下一个可行的零位置:
. 0 0 . . .
只有一种方法可以放置它:
. 0 0 . . .
. 0 0 1 . 1
现在让我们尝试拟合 3,宾果游戏,它拟合了:
. 0 0 . . .
. 0 0 1 . 1
3 0 0 1 3 1
现在您可以停止搜索或尝试寻找其他解决方案。在这种情况下,只有另一种解决方案,即该解决方案的反射,但有 300 种方法可以放置从 1 到 8 的数字,例如。
这种方法几乎是蛮力的,但在实践中,没有很多有效的方法来填充数组,因此可以及早检测到错误的路径。也许将大数字放在第一位可以提供更好的性能。您可以使用它并测量它。
这是一个可以做到这一点的程序。(它可能看起来更像 C 而不是 Go。没关系。)
package main
import "fmt"
func fit_r(res[] int, a[] int, i int) int {
n := len(a);
if i == n {
fmt.Printf("%v\n", res);
return 1;
} else {
count := 0;
m := a[i];
for j := 0; j < 2*n - 1 - m; j++ {
if res[j] == -1 && res[j + 1 + m] == -1 {
// place values
res[j] = m;
res[j + 1 + m] = m;
// test further values
count += fit_r(res, a, i + 1);
// clean up and remove values again
res[j] = -1;
res[j + 1 + m] = -1;
}
}
return count;
}
}
func fit(a[] int) int {
res := make([] int, 2 * len(a));
for i := range res {
res[i] = -1;
}
return fit_r(res, a, 0);
}
func main() {
list := [] int {0, 1, 2, 3};
n := fit(list);
fmt.Println(n, "solutions");
}
- 1 回答
- 0 关注
- 91 浏览
添加回答
举报