问题描述
将 30 条鱼放入 10 个桶,每个桶可放 0~10 条,有多少种排列
分析
将 n 条鱼放入 k 个桶,每个桶最多 m 条
dp[n,k] = sum(dp[n-1,k-j]), 0<=j<=m
有排列
按照上式求解
func splitFish(bucketNum, fishNum, limit int) int {
var dp = make([][]int, bucketNum+1)
for i := range dp {
dp[i] = make([]int, fishNum+1)
}
for i := 0; i <= limit; i++ {
dp[1][i] = 1
}
for i := 2; i <= bucketNum; i++ {
for j := 0; j <= fishNum; j++ {
for k := 0; k <= limit; k++ {
if j >= k {
dp[i][j] += dp[i-1][j-k]
}
}
}
}
return dp[bucketNum][fishNum]
}
无排列
无排列的结果集一定是单调递增/减,按照此规则过滤
func splitFish(bucketNum, fishNum, limit int) int {
var dp = make([][]int, bucketNum+1)
for i := range dp {
dp[i] = make([]int, fishNum+1)
}
//保存结果集
var dpRes = make([][][][]int, bucketNum+1)
for i := range dpRes {
dpRes[i] = make([][][]int, fishNum+1)
}
for i := 0; i <= limit; i++ {
dp[1][i] = 1
dpRes[1][i] = [][]int{{i}}
}
for i := 2; i <= bucketNum; i++ {
for j := 0; j <= fishNum; j++ {
for k := 0; k <= limit; k++ {
if j >= k {
for l, h := range dpRes[i-1][j-k] {
//过滤掉非递增的排列
//过滤已经不在维护的排列,若一直递增,则当前长度应 = i-1
if len(h) == i-1 && k >= h[0] {
dpRes[i][j] = append(dpRes[i][j], append([]int{k}, dpRes[i-1][j-k][l]...))
dp[i][j]++
}
}
}
}
}
}
return dp[bucketNum][fishNum]
}