鱼C论坛

 找回密码
 立即注册
查看: 3063|回复: 39

[已解决]Python:每日一题 329

[复制链接]
发表于 2020-2-11 18:55:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 zltzlt 于 2020-2-11 18:58 编辑

今天的题目:


给出一个非负整数 s 代表背包容量。给出 len(c) 件物品,第 a 件物品的价值为 v[a],体积为 c[a]。

求这个背包最多能装多少价值的物品,返回总价值。

说明:len(c) == len(v)。

注意:每件物品只能用一次。

示例 1:

输入:s = 10, v = [1,2,3], c = [3,5,7]
输出:4
解释:将第 0 件和第 2 件物品放进背包。
示例 2:

输入:s = 10, v = [1,5,3], c = [4,5,7]
输出:6
解释:将第 0 件和第 1 件物品放进背包。


欢迎大家一起答题!
最佳答案
2020-2-11 23:26:31
本帖最后由 fan1993423 于 2020-2-11 23:34 编辑
  1. def fun329(s,v,c):
  2.     list_rel=sorted(list(zip(v,c)),key=lambda x:x[0],reverse=True)
  3.     copy_s,count,result,length=s,0,0,len(list_rel)
  4.     for i in range(length):
  5.         for j in range(i,length):
  6.             s-=list_rel[j][1]
  7.             if s>=0:
  8.                 count+=list_rel[j][0]
  9.             else:
  10.                 s+=list_rel[j][1]
  11.         result=max(count,result)
  12.         count,s=0,copy_s
  13.     return result if result>0 else '背包太小,装不下任何东西'
复制代码

我不知道要不要考虑背包装不下任何东西的情况,为了保守起见,还是多加个判别式

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-11 19:31:25 | 显示全部楼层
1

评分

参与人数 1荣誉 -1 鱼币 -1 收起 理由
zltzlt -1 -1 请不要无意义灌水!

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-11 19:32:43 | 显示全部楼层

刚才我看到有人回了,还以为答出来了
结果...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 19:54:53 | 显示全部楼层
背包问题 动态规划QQ
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 20:31:47 | 显示全部楼层
  1. def f329(s,v,c):
  2.     def dp(a,lv,lc):
  3.         l=[]
  4.         for i,e in enumerate(lc):
  5.             if e<=a:
  6.                 vv=lv.pop(i)
  7.                 cc=lc.pop(i)
  8.                 l.append(dp(a-e,lv,lc)+vv)
  9.                 lv.insert(i,vv)
  10.                 lc.insert(i,cc)
  11.         return max(l+[0])
  12.     return dp(s,v,c)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 21:16:26 | 显示全部楼层
  1. from itertools import combinations

  2. def fun329(s,v,c):
  3.     max_c = 0
  4.     result_list = []
  5.     value_list = []
  6.     for i in range(len(c)):
  7.         if max_c == 0:
  8.             max_c = i+1
  9.         elif sum(sorted(c)[:i+1]) <= s:
  10.             max_c = i+1
  11.         else:
  12.             break
  13.     count = [i for i in range(len(v))]
  14.     for i in range(1,max_c+1):
  15.         for j in combinations(count,i):
  16.             if j not in result_list and sum([c[n] for n in j])<=s:
  17.                 result_list.append(j)
  18.     for i in result_list:
  19.         value_list.append(sum([v[j] for j in i]))
  20.     return max(value_list)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 21:31:52 | 显示全部楼层
体积和价值都是 正整数吗?而且有可能重复?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 21:40:51 | 显示全部楼层
  1. def fun329(s,v,c):
  2.     if(s == 0):
  3.         return 0
  4.     if(sum(c) <= s):
  5.         return sum(v)
  6.     v.insert(0,0)
  7.     c.insert(0,0)
  8.     length = len(c)
  9.     value = [[0 for i in range(s+1)] for i in range(length)]
  10.     for i in range(1,length):
  11.         for j in range(1,s+1):
  12.             if c[i] <= j:
  13.                 value[i][j] = max(value[i-1][j-c[i]]+v[i],value[i-1][j])
  14.             else:
  15.                 value[i][j] = value[i-1][j]
  16.     return value[-1][-1]
复制代码


动态规划吧

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 22:01:02 | 显示全部楼层
def func(s,v,c):
    danjia, ans =[], 0
    for i in range(len(c)):
        danjia += [[v[i]/c[i],i]]
    danjia.sort(reverse=True)
    for i in danjia :
        if s >= c[i[1]] :
            ans += v[i[1]]
            s = s - c[i[1]]
        if s == 0 :
            break   
    return ans

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 22:10:27 | 显示全部楼层
本帖最后由 William4869 于 2020-2-11 22:15 编辑
  1. def f329(s,v,c):
  2.     m=0
  3.     for i in range(len(v)):
  4.         if v[i]>s:continue
  5.         elif v[i]>m:
  6.             m=v[i]
  7.             
  8.         a=[i]
  9.         value=v[i]
  10.         volume=c[i]
  11.       
  12.         if i==len(v)-1:
  13.             break
  14.         
  15.         x=i+1
  16.         while len(a):            
  17.             if volume+c[x]>s:
  18.                 x+=1
  19.             else:
  20.                 a.append(x)
  21.                 value+=v[x]
  22.                 volume+=c[x]
  23.                 if value>m:m=value
  24.                 x+=1
  25.                 #print(a,value,volume)
  26.             while x==len(v):
  27.                 x=a.pop(len(a)-1)
  28.                 value-=v[x]
  29.                 volume-=c[x]
  30.                 x+=1
  31.     return m
复制代码


无脑深搜遍历玩法,感觉会超时,,回头我去看看动态规划是个什么东西

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 23:26:31 | 显示全部楼层    本楼为最佳答案   
本帖最后由 fan1993423 于 2020-2-11 23:34 编辑
  1. def fun329(s,v,c):
  2.     list_rel=sorted(list(zip(v,c)),key=lambda x:x[0],reverse=True)
  3.     copy_s,count,result,length=s,0,0,len(list_rel)
  4.     for i in range(length):
  5.         for j in range(i,length):
  6.             s-=list_rel[j][1]
  7.             if s>=0:
  8.                 count+=list_rel[j][0]
  9.             else:
  10.                 s+=list_rel[j][1]
  11.         result=max(count,result)
  12.         count,s=0,copy_s
  13.     return result if result>0 else '背包太小,装不下任何东西'
复制代码

我不知道要不要考虑背包装不下任何东西的情况,为了保守起见,还是多加个判别式

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
zltzlt + 5 + 5

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 23:31:39 | 显示全部楼层
先来个简单的 背包问题的分治算法 我忘了 先用这个试试 分治算法我再看看
#给出一个非负整数 s 代表背包容量。给出 len(c) 件物品,第 a 件物品的价值为 v[a],体积为 c[a]。
#求这个背包最多能装多少价值的物品,返回总价值。
  1. def fun329(s,v,c):

  2.     def findLowEqual(index,res):
  3.         if index + 1 >= M or c_list[M-1]>res:
  4.             return -1
  5.         else:
  6.             bottom = index + 1
  7.             top = M
  8.             while True:
  9.                 middle = (bottom + top)//2
  10.                 temp = c_list[middle]
  11.                 if temp > res:
  12.                     bottom = middle
  13.                 else:
  14.                     if middle == index + 1 or c_list[middle - 1]>res:
  15.                         return middle
  16.                     else:
  17.                         top = middle
  18.                         
  19.     def inner(index,res):
  20.         start = findLowEqual(index,res)
  21.         if  start < 0:
  22.             maxNum[0] = max(maxNum[0],tempTotal[0])
  23.         else:
  24.             for index in range(start,M):
  25.                 div = s // c_list[start]
  26.             for i in range(0,min(div+1,number_list[start]+1)):
  27.                 tempTotal[0] += sum(dictionary[c_list[start]][0:i])
  28.                 inner(start,res - i*c_list[start])
  29.                 tempTotal[0] -= sum(dictionary[c_list[start]][0:i])
  30.         
  31.     lenth = len(c)
  32.    
  33.     if lenth == 0:
  34.         return 0
  35.    
  36.     dictionary = {}#c:[v]
  37.     for index in range(0,lenth):
  38.         tempC = c[index]
  39.         tempV = v[index]
  40.         try:
  41.             dictionary[tempC].append(tempV)
  42.         except Exception:
  43.             tempList = [tempV]
  44.             dictionary[tempC] = tempList
  45.    
  46.     number_list = []
  47.     for eachC in dictionary:
  48.         number_list.append(len(dictionary[eachC]))
  49.         dictionary[eachC].sort()
  50.         dictionary[eachC].reverse()
  51.         
  52.     c_list = list(dictionary.keys())
  53.     c_list.sort()
  54.     c_list.reverse()
  55.     M = len(c_list)
  56.    
  57.     maxNum = [0]
  58.     tempTotal = [0]
  59.     for index in range(0,M):
  60.         div = s // c_list[index]
  61.         for i in range(0,min(div+1,number_list[index]+1)):
  62.             tempTotal[0] += sum(dictionary[c_list[index]][0:i])
  63.             inner(index,s - i*c_list[index])
  64.             tempTotal[0] -= sum(dictionary[c_list[index]][0:i])
  65.     return maxNum[0]
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 收起 理由
zltzlt + 2 + 2

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 23:36:28 | 显示全部楼层
TJBEST 发表于 2020-2-11 23:31
先来个简单的 背包问题的分治算法 我忘了 先用这个试试 分治算法我再看看
#给出一个非负整数 s  ...

66行代码啊,牛,那么多代码我肯定脑壳中间要多动一下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-11 23:59:02 | 显示全部楼层
本帖最后由 kinkon 于 2020-2-12 00:00 编辑
  1. def f329(s,v,c):
  2.     n=[0]
  3.     for i,j in enumerate(c):
  4.         if j<=s:
  5.             nv,nc=v.pop(i),c.pop(i)
  6.             n.insert(0,f329(s-j,v,c)+nv)
  7.             v.insert(i,nv)
  8.             c.insert(i,nc)
  9.     return max(n)
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 01:07:18 | 显示全部楼层
s = 10
v = [1,2,3,4]
c = [3,5,7,3]
L=[]
def f329(s:int,v:list,c:list)->int:
    if sum(c)<s:
        L.append(sum(v))
        return L
    else:
        for i in range(len(c)):
            c1=c.copy()
            v1=v.copy()
            c1.remove(c1[i])
            v1.remove(v1[i])
            if sum(c1)<=s:
                L.append(sum(v1))
            else:
                f329(s,v1,c1)
    return max(L)

print(f329(s,v,c))

评分

参与人数 1荣誉 +3 鱼币 +3 收起 理由
zltzlt + 3 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 10:37:05 | 显示全部楼层
fan1993423 发表于 2020-2-11 23:36
66行代码啊,牛,那么多代码我肯定脑壳中间要多动一下

还行吧,代码长的好处在于不用动脑子 就是速度慢点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 11:08:39 | 显示全部楼层
请不要封题,下午我便可给出 无递归的的解法
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 11:26:29 | 显示全部楼层
读了半天,没怎么读懂题目
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-2-12 11:57:35 | 显示全部楼层
第二个版本,背包求解,没用递归,挺快的
  1. def fun329(s,v,c):
  2.     #0/1背包问题 由于 给的条件没有说 每个同体积同价值的个数(或无限) 只能按照0/1背包去算
  3.     #采用循环遍历
  4.     #s是容量 v是价值 c是体积
  5.     M = len(v)
  6.     f = [0 for i in range(0,s + 1)]#临时变量 s + 1长度
  7.     for i in range(0,M):
  8.         for m in range(s,0,-1):
  9.             res = m - c[i]
  10.             if res >= 0:
  11.                 f[m] = max(f[m],f[res] + v[i])
  12.             else:
  13.                 break
  14.     return f.pop()
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 收起 理由
zltzlt + 2 + 2

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-2-12 13:52:50 | 显示全部楼层

输入大数据超时
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-26 23:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表