github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/dp/double11_test.go (about) 1 package dp 2 3 import ( 4 "fmt" 5 "testing" 6 ) 7 8 /* 9 10 双11 满减问题 11 12 购物车中 n 个商品 , 满200减50 ,挑选其中的商品 最小达到满减的条件 13 14 w 满减的券的额度 15 price 购物车中商品的价格 16 */ 17 func double11(w int, price []int) { 18 n := len(price) 19 20 // 定义状态 f(商品id,商品价格) 21 states := make([][]bool, n) 22 wc := 3 * w 23 for i := range states { 24 states[i] = make([]bool, wc+1) // 满减是要超过,所以价格要大于w 25 for j := range states[i] { 26 states[i][j] = false 27 } 28 } 29 30 // 首个状态 31 states[0][0] = true // 首个商品不买 32 states[0][price[0]] = true // 首个商品买 33 // 将问题分解成 n个步骤来解决 34 for i := 1; i < n; i++ { // 遍历每个商品 35 for j := 0; j <= wc; j++ { // 第i个商品不买的情况 36 if states[i-1][j] { // 前一个商品已购买的情况 37 states[i][j] = states[i-1][j] // 不购买 j不用加上价格 38 } 39 } 40 41 for j := 0; j <= wc-price[i]; j++ { // 第i个商品需要购买 42 if states[i-1][j] { 43 states[i][j+price[i]] = true 44 } 45 } 46 } 47 48 min := -1 49 for j := w; j < wc+1; j++ { 50 if states[n-1][j] { // 最小满足条件的最小价格 51 min = j // 找到最低价格 52 break 53 } 54 } 55 if min == -1 { 56 fmt.Println("无解:", min) 57 return 58 } 59 fmt.Println("最低价格是:", min) 60 tmp := min 61 // 逆推有哪些商品 62 sum := 0 63 for i := n - 1; i >= 1; i-- { 64 if tmp-price[i] >= 0 && states[i-1][tmp-price[i]] { //states[i-1][tmp-price] 说明购买了 65 // 最小商品价格减去一个商品的价格,去状态表查看中是否有购买,如果有购买就是的 66 fmt.Printf("需要购买第 %v个商品 价格是 %v\n", i, price[i]) 67 tmp -= price[i] 68 sum += price[i] 69 } // states[i-1][tmp] 说明没有被购买 70 } 71 if tmp > 0 && tmp-price[0] == 0 { 72 // 第一个商品也购买 73 fmt.Printf("需要购买第 %v个商品 价格是 %v\n", 0, price[0]) 74 sum += price[0] 75 } 76 fmt.Println("sum:", sum) 77 } 78 79 func TestDouble11(t *testing.T) { 80 sl := []int{3, 5, 7, 1, 2, 8, 9} 81 double11(36, sl) 82 }