Jelajahi Sumber

AC 2008 2 D large

dengxinyi 6 tahun lalu
induk
melakukan
f5ecd84fb9
3 mengubah file dengan 136 tambahan dan 49 penghapusan
  1. 20 0
      2008/2/D/D-large-answers.out
  2. 50 49
      2008/2/D/main.go
  3. 66 0
      2008/2/D/utils.go

+ 20 - 0
2008/2/D/D-large-answers.out

@@ -0,0 +1,20 @@
+Case #1: 690
+Case #2: 638
+Case #3: 859
+Case #4: 431
+Case #5: 875
+Case #6: 601
+Case #7: 513
+Case #8: 895
+Case #9: 47842
+Case #10: 412
+Case #11: 693
+Case #12: 795
+Case #13: 355
+Case #14: 20430
+Case #15: 709
+Case #16: 824
+Case #17: 1
+Case #18: 921
+Case #19: 264
+Case #20: 824

+ 50 - 49
2008/2/D/main.go

@@ -4,46 +4,6 @@ import (
 	"fmt"
 )
 
-func nextPerm(nums []int) bool {
-	n := len(nums)
-	if n < 2 {
-		return false
-	}
-	i := n - 2
-	for ; 0 <= i && nums[i+1] <= nums[i]; i-- {
-	}
-	if i == -1 {
-		return false
-	}
-	j := i + 1
-	for ; j+1 < n && nums[i] < nums[j+1]; j++ {
-	}
-	nums[i], nums[j] = nums[j], nums[i]
-	for l, r := i+1, n-1; l < r; l, r = l+1, r-1 {
-		nums[l], nums[r] = nums[r], nums[l]
-	}
-	return true
-}
-
-func countGroup(s string, perm []int) int {
-	n, k := len(s), len(perm)
-	prevByte := s[perm[0]]
-	cnt := 1
-	for offset := 0; offset < n; offset += k {
-		i := 0
-		if offset == 0 {
-			i = 1
-		}
-		for ; i < k; i++ {
-			if s[offset+perm[i]] != prevByte {
-				cnt++
-			}
-			prevByte = s[offset+perm[i]]
-		}
-	}
-	return cnt
-}
-
 func main() {
 	var N, k int
 	fmt.Scan(&N)
@@ -51,17 +11,58 @@ func main() {
 		fmt.Scan(&k)
 		var S string
 		fmt.Scan(&S)
-		perm := make([]int, k)
-		for i := range perm {
-			perm[i] = i
+		n := len(S)
+		// edge[x][y] means the weight of edge: x -> y
+		// init[x][y] means the weight of edge: init point x -> y
+		edge, init := make([][]int, k), make([][]int, k)
+		for i := 0; i < k; i++ {
+			edge[i], init[i] = make([]int, k), make([]int, k)
 		}
-		minGroup := countGroup(S, perm)
-		for nextPerm(perm) {
-			groupCnt := countGroup(S, perm)
-			if groupCnt < minGroup {
-				minGroup = groupCnt
+		for x := 0; x < k; x++ {
+			for y := 0; y < k; y++ {
+				if x != y {
+					for o := 0; o < n; o += k {
+						if S[o+x] != S[o+y] {
+							edge[x][y]++
+						}
+					}
+					for o := 0; o < n-k; o += k {
+						if S[o+x] != S[o+k+y] {
+							init[x][y]++
+						}
+					} // Note: y -> x and x -> y is NOT THE SAME INIT edge!!!
+				}
+			}
+		}
+		dp := make([][]int, 1<<uint(k))
+		for i := range dp {
+			dp[i] = make([]int, k)
+		}
+		const inf = 1000000
+		ans := inf
+		for beg := 0; beg < k; beg++ {
+			for i := range dp {
+				for j := range dp[i] {
+					dp[i][j] = inf
+				}
+			}
+			dp[1<<uint(beg)][beg] = 1
+			for mask := 0; mask < (1 << uint(k)); mask++ {
+				for i := 0; i < k; i++ {
+					if dp[mask][i] < inf {
+						for j := 0; j < k; j++ {
+							newset := mask | (1 << uint(j))
+							if newset != mask {
+								dp[newset][j] = minInt(dp[newset][j], dp[mask][i]+edge[i][j])
+							}
+						}
+					}
+				}
+			}
+			for i := 0; i < k; i++ {
+				ans = minInt(ans, dp[(1<<uint(k))-1][i]+init[i][beg])
 			}
 		}
-		fmt.Printf("Case #%d: %d\n", cid+1, minGroup)
+		fmt.Printf("Case #%d: %d\n", cid+1, ans)
 	}
 }

+ 66 - 0
2008/2/D/utils.go

@@ -0,0 +1,66 @@
+package main
+
+func minInt(nums ...int) int {
+	min := nums[0]
+	for i := 1; i < len(nums); i++ {
+		if nums[i] < min {
+			min = nums[i]
+		}
+	}
+	return min
+}
+
+func nextPerm(nums []int) bool {
+	n := len(nums)
+	if n < 2 {
+		return false
+	}
+	i := n - 2
+	for ; 0 <= i && nums[i+1] <= nums[i]; i-- {
+	}
+	if i == -1 {
+		return false
+	}
+	j := i + 1
+	for ; j+1 < n && nums[i] < nums[j+1]; j++ {
+	}
+	nums[i], nums[j] = nums[j], nums[i]
+	for l, r := i+1, n-1; l < r; l, r = l+1, r-1 {
+		nums[l], nums[r] = nums[r], nums[l]
+	}
+	return true
+}
+
+func countGroup(s string, perm []int) int {
+	n, k := len(s), len(perm)
+	prevByte := s[perm[0]]
+	cnt := 1
+	for offset := 0; offset < n; offset += k {
+		i := 0
+		if offset == 0 {
+			i = 1
+		}
+		for ; i < k; i++ {
+			if s[offset+perm[i]] != prevByte {
+				cnt++
+			}
+			prevByte = s[offset+perm[i]]
+		}
+	}
+	return cnt
+}
+
+func slowSolution(s string, k int) (min int) {
+	perm := make([]int, k)
+	for i := range perm {
+		perm[i] = i
+	}
+	min = countGroup(s, perm)
+	for nextPerm(perm) {
+		groupCnt := countGroup(s, perm)
+		if groupCnt < min {
+			min = groupCnt
+		}
+	}
+	return
+}