题解 | #购物单#

购物单

https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4

package main

import (
	"fmt"
)

// 直接分成2个数组:主件数组和附件数组

type Product struct {
	Price int // 价格
	Sat   int // 满意度
	Index int // 索引
	Num   int // 编号,0主件,大于0副件
}

// 附件按照总体满意度排序
var attachProducts map[int][]Product
var memo [][]int

func main() {

	attachProducts = make(map[int][]Product, 0)
	mainProducts := make([]Product, 0)

	n, m := 0, 0
	_, _ = fmt.Scan(&n, &m)
	for i := 1; i <= m; i++ {
		v, p, q := 0, 0, 0
		_, _ = fmt.Scan(&v, &p, &q)

		if q == 0 {
			mainProducts = append(mainProducts, Product{
				Price: v,
				Sat:   p,
				Index: i,
			})
		} else {
			if _, ok := attachProducts[q]; !ok {
				attachProducts[q] = make([]Product, 0)
			}
			attachProducts[q] = append(attachProducts[q], Product{
				Price: v,
				Sat:   p,
				Index: i,
			})
		}
	}

	memo = make([][]int, n+1)
	for i := 0; i < len(memo); i++ {
		tmp := make([]int, 0)
		for j := 0; j <= len(mainProducts); j++ {
			tmp = append(tmp, -666)
		}
		memo[i] = tmp
	}

	fmt.Println(maxSatisfy(mainProducts, 0, n))
}

func maxSatisfy(mainProducts []Product, i int, n int) int {
	if n < 0 { // 先判断n再判断i
		return -(1 << 61)
	}

	if i == len(mainProducts) || n == 0 {
		return 0
	}

	if memo[n][i] != -666 {
		return memo[n][i]
	}

	choose := maxSatisfy(mainProducts, i+1, n-mainProducts[i].Price) + mainProducts[i].Price*mainProducts[i].Sat
	notChoose := maxSatisfy(mainProducts, i+1, n)

	chooseAttachOne := -1
	chooseAttachTwo := -1

	// 如果选择了第i个主件,那么就可以选择最多2个该主件的附件

	//	选1个附件
	index := mainProducts[i].Index
	attach := attachProducts[index]
	if len(attach) >= 1 {
		for first := 0; first < len(attach); first++ {
			tmp := maxSatisfy(mainProducts, i+1, n-mainProducts[i].Price-attach[first].Price) +
				mainProducts[i].Price*mainProducts[i].Sat + attach[first].Price*attach[first].Sat
			if tmp > chooseAttachOne {
				chooseAttachOne = tmp
			}
		}
	}

	//	选2个附件
	if len(attach) >= 2 {
		for first := 0; first < len(attach)-1; first++ {
			for second := first + 1; second < len(attach); second++ {
				tmp := maxSatisfy(mainProducts, i+1, n-mainProducts[i].Price-attach[first].Price-attach[second].Price) +
					mainProducts[i].Price*mainProducts[i].Sat + attach[first].Price*attach[first].Sat +
					attach[second].Price*attach[second].Sat

				if tmp > chooseAttachTwo {
					chooseAttachTwo = tmp
				}
			}
		}
	}
	
	memo[n][i] = max(notChoose, max(choose, max(chooseAttachOne, chooseAttachTwo)))
	return memo[n][i]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

全部评论
1. 把所有物品分成主件和附件,n为当前剩余的钱,i为选择的主件,则 dp(n,i) = max(不选i,选i+0件附件,选i+1件附件,选i+2件附件) 2. 用个memo备忘录
点赞
送花
回复
分享
发布于 2022-11-23 08:04 广东

相关推荐

安徽省移动公司 IT部门 一年税前14w
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务