题解 | #购物单#

购物单

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

package main

import (
	"fmt"

)

func main() {
    N,m:= 0,0
    fmt.Scan(&N, &m)

    val := make([][]int, 0)
    wei := make([][]int, 0)
    maj := make([]int, 0)
    satis := make(map[int][]int, 0)
    cost := make(map[int][]int, 0)
    for  {
        v,p,q := 0,0,0
        n, _ := fmt.Scan(&v,&p,&q)
        if n == 0 {
            break
        }

        val = append(val, []int{v}) // 价格
        wei = append(wei, []int{p}) // 重要度
        maj = append(maj, q) // 主件/附件
        if q == 0 {
            satis[len(val)] = []int{v * p}    // 主件满意度
            cost[len(val)] = []int{v}         // 主件价格
        }
        
    }


    // key是主件索引,val是他的几种价值情况
    // 计算有附件时的满意度
    // 对应j=0~3 主件;主件+附件1;主件+附件2;主件+附件1+附件2

    for i, v := range maj {
        if v == 0 {
            // 主件跳过
            continue
        }
    
        // 将附件的三种情况添加到主件的价格和重要度中

        // 将附件加入到主件中,可能是主件+附件1,或者主件+附件2
        // 计算主件满意度+附件1/2满意度
        satis[v] = append(satis[v], satis[v][0] + val[i][0] * wei[i][0])
        cost[v] = append(cost[v], cost[v][0] + val[i][0])

        if len(satis[v]) > 2 { 
            // 说明该主件已经有附件1了,刚刚加的是附件2,还要加上:主件+附件1+附件2
            // satis[v][1] 就是主件+附件1的情况,不需要再加主件
            satis[v] = append(satis[v], satis[v][1] + val[i][0] * wei[i][0])
            cost[v] = append(cost[v], cost[v][1] + val[i][0])
        }
    }

    // fmt.Println("satis",satis)
    // fmt.Println("cost", cost)

    s := make([][]int, 0)
    c := make([][]int, 0)
    for k, v := range satis {
        s = append(s, v)
        c = append(c, cost[k])
    }


    // 更新物品个数为主件数量
    m = len(s)

    // 声明dp, i为物品是否购买,j为总价格
    // dp[i][j] 表示0-i物品最大满意度
    dp := make([][]int, m)
    for i:=0;i<m;i++ {
        dp[i] = make([]int, N+1)
    }


    // 初始化 第一个物品的dp
    for j:=c[0][0];j<=N;j=j+10 {
        for k, v := range c[0] {
            if j >= v { // 钱够时才放进去
                dp[0][j] = s[0][k]
            }
        }
    }


    for i:=1;i<m;i++ {
        for j:=0;j<=N;j=j+10 {
            // 由于是一组物品,所以每个情况都要判断是否金额足够,然后找到满意度最大的。
            max_s := dp[i-1][j] // 不放入第i个时的满意度
            for k, v := range c[i] {
                if j>= v { // 余额足够, 取最大的一种
                    max_s = max(max_s, dp[i-1][j-v]+s[i][k]) // 记得减去消耗的钱
                }
            }
            dp[i][j] = max_s
        }
    }


    fmt.Println(dp[m-1][N])
}

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

全部评论

相关推荐

不愿透露姓名的神秘牛友
2025-12-17 16:48
今天九点半到公司,我跟往常一样先扫了眼电脑,屁活儿没有。寻思着没事干,就去蹲了个厕所,回来摸出手机刷了会儿。结果老板刚好路过,拍了我一下说上班别玩手机,我吓得赶紧揣兜里。也就过了四十分钟吧,我的直属领导把我叫到小隔间,上来就给我一句:“你玩手机这事儿把老板惹毛了,说白了,你可以重新找工作了,等下&nbsp;HR&nbsp;会来跟你谈。”&nbsp;我当时脑子直接宕机,一句话都没憋出来。后面&nbsp;HR&nbsp;找我谈话,直属领导也在旁边。HR&nbsp;说我这毛病不是一次两次了,属于屡教不改,不光上班玩手机,还用公司电脑看论文、弄学校的事儿。我当时人都傻了,上班摸鱼是不对,可我都是闲得发慌的时候才摸啊!而且玩手机这事儿,从来没人跟我说过后果这么严重,更没人告诉我在公司学个习也算犯错!连一次口头提醒都没有,哪儿来的屡教不改啊?更让我膈应的是,昨天部门刚开了会,说四个实习生里留一个转正,让大家好好表现。结果今天我就因为玩手机被开了。但搞笑的是,开会前直属领导就把我叫去小会议室,明明白白告诉我:“转正这事儿你就别想了,你的学历达不到我们部门要求,当初招你进来也没打算给你这个机会。”合着我没入贵厂的眼是吧?可我都已经被排除在转正名单外了,摸个鱼至于直接把我开了吗?真的太离谱了!
rush$0522:转正名单没进,大概率本来就没打算留你
摸鱼被leader发现了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务