2-B-1, 2-B-2

This commit is contained in:
xkm
2026-05-11 20:23:54 +08:00
parent 7ccb2ea522
commit 459af53f27
6 changed files with 236 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
module algo
go 1.26.3
+41
View File
@@ -0,0 +1,41 @@
package algo
func DP(t1 []int, t2 []int, e1 []int, e2 []int) int {
Len := len(t1)
if len(t2) != Len || len(e1) != Len || len(e2) != Len {
return -1
}
dp1 := make([]int, Len)
dp2 := make([]int, Len)
dp1[0], dp2[0] = t1[0], t2[0]
for i := 1; i < Len; i++ {
dp1[i] = min(dp1[i-1], dp2[i-1]+e2[i-1]) + t1[i]
dp2[i] = min(dp2[i-1], dp1[i-1]+e1[i-1]) + t2[i]
}
return min(dp1[Len-1], dp2[Len-1])
}
func Rec(t1 []int, t2 []int, e1 []int, e2 []int) int {
Len := len(t1)
if len(t2) != Len || len(e1) != Len || len(e2) != Len {
return -1
}
return min(rec(t1, t2, e1, e2))
}
func rec(t1 []int, t2 []int, e1 []int, e2 []int) (int, int, int, int) {
Len := len(t1)
if Len == 1 {
return t1[0], 0x3f3f3f3f3f3f3f3f, 0x3f3f3f3f3f3f3f3f, t2[0]
}
mid := Len / 2
a11, a12, a21, a22 := rec(t1[:mid], t2[:mid], e1[:mid], e2[:mid])
b11, b12, b21, b22 := rec(t1[mid:], t2[mid:], e1[mid:], e2[mid:])
s1 := e1[mid-1]
s2 := e2[mid-1]
return min(a11+b11, a11+s1+b21, a12+s2+b11, a12+b21), min(a11+b12, a11+s1+b22, a12+s2+b12, a12+b22),
min(a21+b11, a21+s1+b21, a22+b21, a22+s2+b11), min(a21+b12, a21+s1+b22, a22+b22, a22+s2+b12)
}
+75
View File
@@ -0,0 +1,75 @@
package algo
import (
"fmt"
"math/rand"
"testing"
)
type testCase struct {
t1 []int
t2 []int
e1 []int
e2 []int
}
func randomCase(rng *rand.Rand, n int) testCase {
tc := testCase{
t1: make([]int, n),
t2: make([]int, n),
e1: make([]int, n),
e2: make([]int, n),
}
for i := 0; i < n; i++ {
tc.t1[i] = rng.Intn(1000)
tc.t2[i] = rng.Intn(1000)
tc.e1[i] = rng.Intn(1000)
tc.e2[i] = rng.Intn(1000)
}
return tc
}
func TestRecAndDPMatchOnRandomData(t *testing.T) {
rng := rand.New(rand.NewSource(1))
const casesPerLen = 200
for n := 1; n <= 128; n++ {
for caseIdx := 0; caseIdx < casesPerLen; caseIdx++ {
tc := randomCase(rng, n)
gotRec := Rec(tc.t1, tc.t2, tc.e1, tc.e2)
gotDP := DP(tc.t1, tc.t2, tc.e1, tc.e2)
if gotRec != gotDP {
t.Fatalf("mismatch for len=%d case=%d: Rec=%d DP=%d t1=%v t2=%v e1=%v e2=%v",
n, caseIdx, gotRec, gotDP, tc.t1, tc.t2, tc.e1, tc.e2)
}
}
}
}
func BenchmarkDP(b *testing.B) {
benchmarkByLen(b, "DP", DP)
}
func BenchmarkRec(b *testing.B) {
benchmarkByLen(b, "Rec", Rec)
}
func benchmarkByLen(b *testing.B, name string, fn func([]int, []int, []int, []int) int) {
lengths := []int{1, 10, 100, 1000, 10000, 100000, 1000000, 10000000}
for _, n := range lengths {
n := n
b.Run(fmt.Sprintf("%s/len=%d", name, n), func(b *testing.B) {
rng := rand.New(rand.NewSource(int64(n)))
tc := randomCase(rng, n)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = fn(tc.t1, tc.t2, tc.e1, tc.e2)
}
})
}
}