add 41_dp

This commit is contained in:
Shang, Rocky 2019-06-22 23:16:08 +08:00
parent fdf388e069
commit 22028106dd
2 changed files with 158 additions and 0 deletions

View 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)
}
}
}

View 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)
}