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 關注
- 126 瀏覽
添加回答
舉報