add 41_dp
This commit is contained in:
parent
fdf388e069
commit
22028106dd
102
go/41_dynamic_programming/backtracking/leastcoins.go
Normal file
102
go/41_dynamic_programming/backtracking/leastcoins.go
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package dp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const intMax = int(^uint(0) >> 1)
|
||||||
|
|
||||||
|
var Cnt int
|
||||||
|
|
||||||
|
// LeastCoins find least number of coins of which the total values are equals a given one
|
||||||
|
func LeastCoins(targetTotal int, coinOptions []int) int {
|
||||||
|
minNum := intMax
|
||||||
|
|
||||||
|
memo := make([][]int, targetTotal+1)
|
||||||
|
for i := range memo {
|
||||||
|
memo[i] = make([]int, len(coinOptions))
|
||||||
|
}
|
||||||
|
fmt.Println("start")
|
||||||
|
leastCoins(&minNum, 0, targetTotal, len(coinOptions)-1, coinOptions, memo)
|
||||||
|
fmt.Println("end")
|
||||||
|
|
||||||
|
return minNum
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func leastCoins(minNum *int, cNum, totalValue, opIndex int, coinOptions []int, memo [][]int) {
|
||||||
|
Cnt++
|
||||||
|
if 0 == totalValue {
|
||||||
|
if cNum < *minNum {
|
||||||
|
*minNum = cNum
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if opIndex < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
num4Option := 0
|
||||||
|
remaining := totalValue - coinOptions[opIndex]*num4Option
|
||||||
|
for remaining >= 0 {
|
||||||
|
|
||||||
|
if opIndex != 0 {
|
||||||
|
if shouldSkip(memo, remaining, opIndex-1, cNum+num4Option) {
|
||||||
|
goto Next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leastCoins(minNum, cNum+num4Option, remaining, opIndex-1, coinOptions, memo)
|
||||||
|
|
||||||
|
Next:
|
||||||
|
num4Option++
|
||||||
|
remaining = totalValue - coinOptions[opIndex]*num4Option
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldSkip(memo [][]int, totalValue, nextOpIdex, cNum int) bool {
|
||||||
|
if memo[totalValue][nextOpIdex] > 0 && memo[totalValue][nextOpIdex] <= cNum {
|
||||||
|
fmt.Printf("skip,%d, %d as %d <= %d \n", totalValue, nextOpIdex, memo[totalValue][nextOpIdex], cNum)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if memo[totalValue][nextOpIdex] == 0 || memo[totalValue][nextOpIdex] > cNum {
|
||||||
|
memo[totalValue][nextOpIdex] = cNum
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func LeastCoins2(targetTotal int, coinOptions []int) int {
|
||||||
|
|
||||||
|
minNum := intMax
|
||||||
|
memo := make([][]bool, targetTotal)
|
||||||
|
for i := range memo {
|
||||||
|
memo[i] = make([]bool, targetTotal/coinOptions[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("start")
|
||||||
|
leastCoins2(&minNum, targetTotal, coinOptions, 0, 0, memo)
|
||||||
|
fmt.Println("end")
|
||||||
|
|
||||||
|
return minNum
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func leastCoins2(minNum *int, targetTotal int, coinOptions []int, cNum, cValue int, memo [][]bool) {
|
||||||
|
Cnt++
|
||||||
|
if cValue == targetTotal {
|
||||||
|
if *minNum > cNum {
|
||||||
|
*minNum = cNum
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, coin := range coinOptions {
|
||||||
|
if coin+cValue <= targetTotal && !memo[cValue+coin-1][cNum] {
|
||||||
|
memo[cValue+coin-1][cNum] = true
|
||||||
|
leastCoins2(minNum, targetTotal, coinOptions, cNum+1, cValue+coin, memo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
go/41_dynamic_programming/backtracking/leastcoins_test.go
Normal file
56
go/41_dynamic_programming/backtracking/leastcoins_test.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package dp
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestFindLeastCoins(t *testing.T) {
|
||||||
|
|
||||||
|
coinOptions := []int{1, 3, 5, 10, 50}
|
||||||
|
|
||||||
|
Cnt = 0
|
||||||
|
result := LeastCoins(9, coinOptions)
|
||||||
|
|
||||||
|
t.Log("test 1 =====================")
|
||||||
|
if result != 3 {
|
||||||
|
t.Logf("least coins %d", result)
|
||||||
|
t.Error("failed")
|
||||||
|
}
|
||||||
|
t.Logf("cnt===%d", Cnt)
|
||||||
|
|
||||||
|
Cnt = 0
|
||||||
|
t.Log("test 2 =====================")
|
||||||
|
result = LeastCoins(36, coinOptions)
|
||||||
|
|
||||||
|
if result != 5 {
|
||||||
|
t.Logf("least coins %d", result)
|
||||||
|
t.Error("failed")
|
||||||
|
}
|
||||||
|
t.Logf("cnt===%d", Cnt)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFindLeastCoins2(t *testing.T) {
|
||||||
|
|
||||||
|
coinOptions := []int{1, 3, 5, 10, 50}
|
||||||
|
|
||||||
|
Cnt = 0
|
||||||
|
result := LeastCoins2(9, coinOptions)
|
||||||
|
|
||||||
|
t.Log("test 1 =====================")
|
||||||
|
if result != 3 {
|
||||||
|
t.Logf("least coins %d", result)
|
||||||
|
t.Error("failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("cnt===%d", Cnt)
|
||||||
|
|
||||||
|
Cnt = 0
|
||||||
|
t.Log("test 2 =====================")
|
||||||
|
result = LeastCoins2(36, coinOptions)
|
||||||
|
|
||||||
|
if result != 5 {
|
||||||
|
t.Logf("least coins %d", result)
|
||||||
|
t.Error("failed")
|
||||||
|
}
|
||||||
|
t.Logf("cnt===%d", Cnt)
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user