优惠券组合小例子

优惠券组合小例子

优惠券的使用贯穿于我们生活的日常。"美团外卖"和"饿了么"成为大学时代的难忘记忆!如何精准凑单是门技术活,如何精准凑单以让自己获得最大满减优惠是众多小伙伴的一大需求。本文以一个小例子来实现对凑单这一场景的再现。
input1:点选的n道菜肴对应的单价列表quotion=[v1,v2,v3,…,vn];
input2:满减的优惠券额度man_N_jian;
output:最优的凑单匹配选项对应价格
为实现代码的简便,默认list中元素位置与菜肴名称一一对应。
算法时间复杂度:O(2^n)。
空间复杂度:O(n*2^n)。

  • 算法思想:
  1. 价格列表quotion中存在man_N_jian额度,直接返回man_N_jian表示True
  2. 选择每一道菜肴本身是一个0-1整数规划,那么使用n个0或1的组合序列(falgArray)来与对应菜肴单价相乘加即可获得一个和数total,即: total =vi*falgArray[i],i=1,2,…n。如果和数total能先落在区间[man_N_jian, man_N_jian+5]内,然后计算delta=abs(total-man_N_jian),并保留当前的最小值-----min1,历史的最小值-----min2。将每一轮计算的三元组(total, falgArray,min2)存入list中以备最后找出最小差值对应的菜肴组合序列。
  • 代码
#本质上就是一个0-1整数规划
#简易菜单
#quotion={'红烧牛肉':15, '红烧鱼':11, '可乐鸡翅':2, '牛肉':8,'北京烤鸭':3,'白菜':24,'花生':6,'西兰花':7,'土豆':32,'农家小炒肉':2,'羊肉':9}#,'西红柿炒蛋':20}

def isMixDiscount(quotion,man_N_jian,n):
    #quotion=quotion1.values()
    min1=0
    min2=5
    #可以凑成满减的最低额度
    if man_N_jian in quotion:
        binary_array.append(man_N_jian)
        return True,binary_array
    #不可以凑成满减的最低额度
    else:
        #算法复杂度(2^n)
        for item in range(1,pow(2,n)):
            total=0
            falgArray=[]
            falgArray=list(map(int,bin(item)[2:])) #转为二进制
            for j in range(n-len(falgArray)): #填0补齐
                falgArray.append(0)
            for k in range(len(falgArray)):
                total+=quotion[k]*falgArray[k]
            if (man_N_jian<=total) and (total<man_N_jian+5):
                min1=abs(total-man_N_jian)
                if min1<min2:
                    min2=min1
                    binary_array.append((total,falgArray,min2))
                else:
                    pass
            else:
                continue
    #找出最小满减方案
    min3=min([binary_array[i][2] for i in range(len(binary_array))])
    result=[binary_array[i][0:2] for i in range(len(binary_array)) if binary_array[i][2]==min3 ] #返回点餐的菜品价格
    return [quotion[i] for i in range(len(result[0][1])) if result[0][1][i]==1],result

#这里出现错误:原因是字典的items是无序的。
#result=isMixDiscount(list(map(lambda x:x[1],quotion.items())),man_N_jian,n)

binary_array=[]
n=int(input('n='))
man_N_jian=eval(input('man_N_jian='))
import time
start=time.time()
#caidan=[15, 11,24,6, 2, 8,3,7,32,2,9,4,20]
#caidan2与caidan1一一对应.
caidan2=['红烧牛肉', '红烧鱼', '可乐鸡翅', '牛肉','北京烤鸭','白菜','花生','西兰花','土豆','农家小炒肉','羊肉']#,'西红柿炒蛋':20}
caidan1=[15, 11,24,6, 2, 8,3,7,32,2,9,4,60,45,36,90]

while True:
    if n<len(caidan1):
        quotion=caidan1
        result=isMixDiscount(quotion,man_N_jian,n)
        print('最优解:',result)
        #返回菜名
        #记录菜名的索引列表
        cailist=[]
        for i in range(len(result[1][0][1])):
            if result[1][0][1][i]==1:
                cailist.append(i)
        #[caidan[index1] for index1,index2 in list(zip(cailist,result[0]))]
        item=[(caidan2[index1],index2) for index1,index2 in list(zip(cailist,result[0]))]
        #[(caidan[result[1][0][1].index(index)]) for index in result[1][0][1] ]
        print('菜肴信息:',item) 
        break
    else:
        print('对于n=请输入%d以内的某个整数' % len(caidan1))
        print('对于man_N_jian=请输入100以内的某个整数')
        n=int(input('n='))
        man_N_jian=eval(input('man_N_jian='))
print('titaltime:',time.time()-start)

  • 代码效果
#情况1:man_N_jian在单价列表quotion中
n=11
man_N_jian=20
最优解: (True, [20])
titaltime: 0.001999378204345703

#情况2:man_N_jian不在在单价列表quotion中,即需要自由组合
#例子1:
n=5
man_N_jian=20
最优解: ([15, 6], [(21, [1, 0, 0, 1, 0])])
titaltime: 0.0010056495666503906
#例子2:
n=8
man_N_jian=20
最优解: ([15, 2, 3], [(20, [1, 0, 0, 0, 1, 0, 1, 0])])
titaltime: 0.0020046234130859375
#例子3:
n=14
man_N_jian=100
最优解: ([15, 11, 24, 8, 3, 7, 32], [(100, [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0])])
titaltime: 0.08823323249816895
#例子4:
n=17
man_N_jian=100
对于n=请输入16以内的某个整数
对于man_N_jian=请输入100以内的某个整数

n=14
man_N_jian=100
最优解: ([15, 11, 24, 8, 3, 7, 32], [(100, [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0])])
titaltime: 7.192155838012695

例5:
n=14
man_N_jian=100
最优解: ([15, 11, 24, 8, 3, 7, 32], [(100, [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0])])
菜肴信息: [('红烧牛肉', 15), ('红烧鱼', 11), ('可乐鸡翅', 24), ('白菜', 8), ('花生', 3), ('西兰花', 7), ('土豆', 32)]
titaltime: 0.11931896209716797

猜你喜欢

转载自blog.csdn.net/jp_zhou256/article/details/82994359