首页 > 编程语言 >算法-购物车问题

算法-购物车问题

时间:2024-03-20 20:33:05浏览次数:32  
标签:attachments 购物车 问题 附件 算法 points key prices 主件

算法-购物车问题

问题描述

终于发了年终奖准备去网上购物,如何能在有限的预算内,得到最大的收益呢。如果只到这里的话,其实就是一个背包问题,可以参考链接

然鹅还有其他条件:

可以购买的物品分为两类:主物品可以单独购买,附件物品只能在已经购买了主物品的情况下购买。例如,要购买打印机,需要先购买电脑。另外,一个主件商品,最多有2个附件商品。

计算满意度=物品价格*物品重要性

其实还有一个默认条件,那就是每个物品默认只购买一次。想想也很合理,又不是消耗品,多买只会降低边际效应。

问题抽象

用代码来抽象表示,大概如下这样

# 总预算1000,可选商品数量5个
m = 1000
n = 5

物品价格和重要性,以及主附关系如下:(题目还有个提示是,价格都是10的倍数

# 价格 重要性 主件还是附件,1说明他们是第一件物品的附件
goods = [
    [800, 2, 0],
    [400, 5, 1],
    [300, 5, 1],
    [400, 3, 0],
    [500, 2, 0]
]

问题分解

因为最终考虑的是商品的满意度,也就是计算价格*重要度,所以先对商品数据做处理

def get_value(price, point):
    """计算价格和满意度"""
    value_ = [price, price*point]
    return value_
  • 每次考虑是否购入一种商品时,因为附件至多有2个,有以下4种情况:
  1. 只购买主件
  2. 购买主件+附件1
  3. 购买主件+附件2
  4. 购买主件+附件1+附件2
def work(key, value, attachments):
    """模拟4种情况"""
    prices, points = [], []
    # 1.仅有主件
    prices.append(value[0])
    points.append(value[1])
    if key in attachments:
        # 2. 主件 + 附件1
        prices.append(prices[0] + attachments[key][0][0])
        points.append(points[0] + attachments[key][0][1])
        if len(attachments[key]) == 2:
            # 3.主件+附件2
            prices.append(prices[0] + attachments[key][1][0])
            points.append(prices[0] + attachments[key][1][1])
            # 4.主件+ 附件1 + 附件2
            prices.append(prices[0] + attachments[key][0][0] + attachments[key][1][0])
            points.append(points[0] + attachments[key][0][1] + attachments[key][1][1])
    return prices, points

用2个字典分别存储主件和附件,一个res列表存储最优解

    # 主件 附件 结果列表
    main_goods, attachments, res_list = {}, {}, [0] *(m+1)
  • 遍历商品,将主件和附件,分别添加进字典
    for i in range(n):
        price, point, att = goods[i][0], goods[i][1], goods[i][2]
        # 把商品简化成价格 和  满意度
        good = get_value(price, point)
        # 如果是主件
        if att == 0:
            # 添加进主件字典, 注意i+1,这样就和附件的主件对应上了
            main_goods[i+1] = good
        # 如果是附件    
        else:
            # 如果该附件编号key已经存在了
            if att in attachments:
                # 这个key下的列表,加上该附件商品
                attachments[att].append(good)
            # 不存在就创建这个key   
            else:
                attachments[att] = [good]
  • 最终,对主件商品进行遍历,计算每个预算的结果,这里类似于背包问题里一行内的值计算
    # 对主件字典进行遍历
    for key, value in main_goods.items():
        # prices列表和points列表,分别计算了4种情况的价格和满意度
        prices, points = work(key, value, attachments)
        # 对一列的所有值进行遍历
        for j in range(m, -1, -10):  # 价格是10的倍数
            # 判断价格是否在预算内
            for k in range(len(prices)):
                # 如果在预算内
                if j - prices[k] >= 0:
                    # 最优解在 上一次的最优解 和 剩余预算的最优解+当前满意度 之间取大的那个
                    res_list[j] = max(res_list[j], res_list[j-prices[k]] + points[k])

最后返回结果,

    return res_list[m]

完整代码如下

def get_value(price, point):
    """计算价格和满意度"""
    value_ = [price, price*point]
    return value_

def work(key, value, attachments):
    """模拟4种情况"""
    prices, points = [], []
    # 1.仅有主件
    prices.append(value[0])
    points.append(value[1])
    if key in attachments:
        # 2. 主件 + 附件1
        prices.append(prices[0] + attachments[key][0][0])
        points.append(points[0] + attachments[key][0][1])
        if len(attachments[key]) == 2:
            # 3.主件+附件2
            prices.append(prices[0] + attachments[key][1][0])
            points.append(prices[0] + attachments[key][1][1])
            # 4.主件+ 附件1 + 附件2
            prices.append(prices[0] + attachments[key][0][0] + attachments[key][1][0])
            points.append(points[0] + attachments[key][0][1] + attachments[key][1][1])
    return prices, points

def main():
    # 总预算1000, 可选商品5
    m, n = 1000, 5
    # 商品的价格 重要度 是否附件
    goods = [
        [800, 2, 0],
        [400, 5, 1],
        [300, 5, 1],
        [400, 3, 0],
        [500, 2, 0]
    ]
    # 主件 附件
    main_goods, attachments, res_list = {}, {}, [0] * (m+1)
    for i in range(n):
        price, point, att = goods[i][0], goods[i][1], goods[i][2]
        # 把商品简化成价格 和  满意度
        good = get_value(price, point)
        # 如果是主件
        if att == 0:
            # 添加进主件字典
            main_goods[i+1] = good
        # 如果是附件
        else:
            # 如果该附件编号key已经存在了
            if att in attachments:
                # 这个key下的列表,加上该附件商品
                attachments[att].append(good)
            # 不存在就创建这个key
            else:
                attachments[att] = [good]

    # 对主件字典进行遍历
    for key, value in main_goods.items():
        # prices列表和points列表,分别计算了4种情况的价格和满意度
        prices, points = work(key, value, attachments)
        # 对一列的所有值进行遍历
        for j in range(m, -1, -10):  # 价格是10的倍数
            # 判断价格是否在预算内
            for k in range(len(prices)):
                # 如果在预算内
                if j - prices[k] >= 0:
                    # 最优解在 上一次的最优解 和 剩余预算的最优解+当前满意度 之间取大的那个
                    res_list[j] = max(res_list[j], res_list[j-prices[k]] + points[k])
    print(res_list)
    return res_list[m]

if __name__ == '__main__':
    print(main())

参考了如下链接:https://blog.csdn.net/kk_gods/article/details/116048116

标签:attachments,购物车,问题,附件,算法,points,key,prices,主件
From: https://blog.csdn.net/kayotin/article/details/136887700

相关文章

  • 贪心算法详解
    贪心1建立数学模型来描述问题2把求解的问题分成若干个子问题3对每一个子问题求解,得到子问题的局部最优解4把子问题的解局部最优解合成原来解问题的一个解总结:局部最优做到全局最优。例题实战1在很久以前,有n个部落居住在平原上,依次编号为1到n,第i个部落的人数为ti,......
  • 约瑟夫环问题
    题目描述约瑟夫环问题:设有n个人围坐一圈,并按顺时针方向1−n编号。从第s个人开始进行报数,报数到第m个人,此人出圈,再从他的下一个人重新开始从1到m的报数进行下去,直到只剩一个人为止。输入人数n;从第s个人开始报数s;报到第几个数m。输出剩下的最后一个人的编号。代码......
  • 目标检测——YOLOX算法解读
    论文:YOLOX:ExceedingYOLOSeriesin2021(2021.7.18)作者:ZhengGe,SongtaoLiu,FengWang,ZemingLi,JianSun链接:https://arxiv.org/abs/2107.08430代码:https://github.com/Megvii-BaseDetection/YOLOXYOLO系列算法解读:YOLOv1通俗易懂版解读SSD算法解读YOLOv......
  • 使用verillog编写KMP字符串匹配算法
    设计思路如下:定义模块的输入输出信号:包括时钟信号clk、复位信号rst、模式串pattern、文本串text以及输出信号match。定义所需寄存器和变量:使用寄存器来存储状态机的状态以及其他控制变量,如模式串数组P、失配函数数组F、模式串位置p_index、文本串位置t_index等。在时钟......
  • 2024.3.20 算法
    求最大公约数0与任何数字的最大公约数都是非0数字。intgcd(intlhs,intrhs){//默认lhs>=rhsif(rhs==0){returnlhs;}returngcd(rhs,lhs%rhs);//辗转相除}冒泡排序for(inti=0;i<n;++i){for(intj=i+1;j<n;++j){if(str[i]>str[j]){swap(str[i],str[j]);//让j始终......
  • spring使用jdk17运行出现编码问题
    遇到一个比较奇怪的问题。这个问题别人也遇到过。https://blog.csdn.net/gao_chuan_g/article/details/115117712一、情况简介使用jdk17+springboot3.x+spring6.x写一个小应用A,其中有一部分代码是用于生成SM2加密后的字符串,这个字符串会再做一些处理,最终会显示在前端的页面。......
  • 芒果YOLOv5改进86:上采样Dysample:顶会ICCV2023,轻量级图像增采样器,通过学习采样来学习上
    ......
  • NOJ南邮上机 矩阵变换问题 PROB1020 Python
    PROB1020   矩阵变换问题描述:给定一个 n×m的矩阵,对于 初始矩阵 中所有值为 1 的元素,重置其 所在行列 的所有元素为 0,最后输出整个修改后的矩阵。输入:输入共包含 1+n行。第一行包两个整数 n 和 m,分别表示矩阵的长和宽,题目保证 2≤n,m≤700且 4≤n×m......
  • HDU 2048:神、上帝以及老天爷(错排问题)
    一、原题链接[Problem-2048(hdu.edu.cn)](https://acm.hdu.edu.cn/showproblem.php?pid=2045)二、题面HDU2006'10ACMcontest的颁奖晚会隆重开始了!为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的:首先,所有参加晚会的人员都将一......
  • 机器人路径规划:基于迪杰斯特拉算法(Dijkstra)的机器人路径规划(提供Python代码)
    迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻......