mirror of
https://github.com/halfrost/LeetCode-Go.git
synced 2025-07-06 17:44:10 +08:00
108 lines
3.9 KiB
Go
108 lines
3.9 KiB
Go
package leetcode
|
||
|
||
import (
|
||
"math"
|
||
)
|
||
|
||
func getMaxGridHappiness(m int, n int, introvertsCount int, extrovertsCount int) int {
|
||
// lineStatus 将每一行中 3 种状态进行编码,空白 - 0,内向人 - 1,外向人 - 2,每行状态用三进制表示
|
||
// lineStatusList[729][6] 每一行的三进制表示
|
||
// introvertsCountInner[729] 每一个 lineStatus 包含的内向人数
|
||
// extrovertsCountInner[729] 每一个 lineStatus 包含的外向人数
|
||
// scoreInner[729] 每一个 lineStatus 包含的行内得分(只统计 lineStatus 本身的得分,不包括它与上一行的)
|
||
// scoreOuter[729][729] 每一个 lineStatus 包含的行外得分
|
||
// dp[上一行的 lineStatus][当前处理到的行][剩余的内向人数][剩余的外向人数]
|
||
n3, lineStatus, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter, lineStatusList, dp := math.Pow(3.0, float64(n)), 0, [729]int{}, [729]int{}, [729]int{}, [729][729]int{}, [729][6]int{}, [729][6][7][7]int{}
|
||
for i := 0; i < 729; i++ {
|
||
lineStatusList[i] = [6]int{}
|
||
}
|
||
for i := 0; i < 729; i++ {
|
||
dp[i] = [6][7][7]int{}
|
||
for j := 0; j < 6; j++ {
|
||
dp[i][j] = [7][7]int{}
|
||
for k := 0; k < 7; k++ {
|
||
dp[i][j][k] = [7]int{-1, -1, -1, -1, -1, -1, -1}
|
||
}
|
||
}
|
||
}
|
||
// 预处理
|
||
for lineStatus = 0; lineStatus < int(n3); lineStatus++ {
|
||
tmp := lineStatus
|
||
for i := 0; i < n; i++ {
|
||
lineStatusList[lineStatus][i] = tmp % 3
|
||
tmp /= 3
|
||
}
|
||
introvertsCountInner[lineStatus], extrovertsCountInner[lineStatus], scoreInner[lineStatus] = 0, 0, 0
|
||
for i := 0; i < n; i++ {
|
||
if lineStatusList[lineStatus][i] != 0 {
|
||
// 个人分数
|
||
if lineStatusList[lineStatus][i] == 1 {
|
||
introvertsCountInner[lineStatus]++
|
||
scoreInner[lineStatus] += 120
|
||
} else if lineStatusList[lineStatus][i] == 2 {
|
||
extrovertsCountInner[lineStatus]++
|
||
scoreInner[lineStatus] += 40
|
||
}
|
||
// 行内分数
|
||
if i-1 >= 0 {
|
||
scoreInner[lineStatus] += closeScore(lineStatusList[lineStatus][i], lineStatusList[lineStatus][i-1])
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 行外分数
|
||
for lineStatus0 := 0; lineStatus0 < int(n3); lineStatus0++ {
|
||
for lineStatus1 := 0; lineStatus1 < int(n3); lineStatus1++ {
|
||
scoreOuter[lineStatus0][lineStatus1] = 0
|
||
for i := 0; i < n; i++ {
|
||
scoreOuter[lineStatus0][lineStatus1] += closeScore(lineStatusList[lineStatus0][i], lineStatusList[lineStatus1][i])
|
||
}
|
||
}
|
||
}
|
||
return dfs(0, 0, introvertsCount, extrovertsCount, m, int(n3), &dp, &introvertsCountInner, &extrovertsCountInner, &scoreInner, &scoreOuter)
|
||
}
|
||
|
||
// 如果 x 和 y 相邻,需要加上的分数
|
||
func closeScore(x, y int) int {
|
||
if x == 0 || y == 0 {
|
||
return 0
|
||
}
|
||
// 两个内向的人,每个人要 -30,一共 -60
|
||
if x == 1 && y == 1 {
|
||
return -60
|
||
}
|
||
if x == 2 && y == 2 {
|
||
return 40
|
||
}
|
||
return -10
|
||
}
|
||
|
||
// dfs(上一行的 lineStatus,当前处理到的行,剩余的内向人数,剩余的外向人数)
|
||
func dfs(lineStatusLast, row, introvertsCount, extrovertsCount, m, n3 int, dp *[729][6][7][7]int, introvertsCountInner, extrovertsCountInner, scoreInner *[729]int, scoreOuter *[729][729]int) int {
|
||
// 边界条件:如果已经处理完,或者没有人了
|
||
if row == m || introvertsCount+extrovertsCount == 0 {
|
||
return 0
|
||
}
|
||
// 记忆化
|
||
if dp[lineStatusLast][row][introvertsCount][extrovertsCount] != -1 {
|
||
return dp[lineStatusLast][row][introvertsCount][extrovertsCount]
|
||
}
|
||
best := 0
|
||
for lineStatus := 0; lineStatus < n3; lineStatus++ {
|
||
if introvertsCountInner[lineStatus] > introvertsCount || extrovertsCountInner[lineStatus] > extrovertsCount {
|
||
continue
|
||
}
|
||
score := scoreInner[lineStatus] + scoreOuter[lineStatus][lineStatusLast]
|
||
best = max(best, score+dfs(lineStatus, row+1, introvertsCount-introvertsCountInner[lineStatus], extrovertsCount-extrovertsCountInner[lineStatus], m, n3, dp, introvertsCountInner, extrovertsCountInner, scoreInner, scoreOuter))
|
||
}
|
||
dp[lineStatusLast][row][introvertsCount][extrovertsCount] = best
|
||
return best
|
||
}
|
||
|
||
func max(a int, b int) int {
|
||
if a > b {
|
||
return a
|
||
}
|
||
return b
|
||
}
|