解背包问题

随机试探

  • 0/1背包问题
  • 随机种子
    • 换一台电脑试试
  • 随机试探
    • 代码
    • 测试
    • 更改限定次数和试探次数测试
  • 贪心算法
    • 打印

0/1背包问题

0/1背包问题书上最后一页

里面提到了穷举法,贪心算法,分支界限法,还列出了动态规划的思路。

2024-11-14 2024-11-15 2024-11-16 2024-11-17 2024-11-18 2024-11-19 2024-11-20 2024-11-21 2024-11-22 2024-11-23 2024-11-24 2024-11-25 2024-11-26 2024-11-27 贪心算法 随机试探法 动态规划 现有任务 0/1背包问题的解法

随机种子

让生成的随机数每次都一样。随机种子一直有用吗?重新打开应用,电脑关了再打开,生成的随机数还是一样吗?

import random
def seedtest(S=0):
    random.seed(S)
    return [random.random() for _ in range(10)]
'''
[0.8444218515250481, 0.7579544029403025, 0.420571580830845, 0.25891675029296335,
 0.5112747213686085, 0.4049341374504143, 0.7837985890347726, 0.30331272607892745,
 0.4765969541523558, 0.5833820394550312]
'''
#重启电脑还是这样的输出。
Python 3.8.0 (tags/v3.8.0:fa919fd, Oct 14 2019, 19:37:50) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.
>>> 
================== RESTART: C:\Program Files\Python38\seed.py ==================
>>> seedtest()
[0.8444218515250481, 0.7579544029403025, 0.420571580830845, 0.25891675029296335, 0.5112747213686085, 0.4049341374504143, 0.7837985890347726, 0.30331272607892745, 0.4765969541523558, 0.5833820394550312]
>>> 

我这里测试是这样的。

换一台电脑试试

也是一样的结果。

Python 3.11.2 (tags/v3.11.2:878ead1, Feb  7 2023, 16:38:35) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license()" for more information.

======================= RESTART: E:/老公/python/seedtest.py ======================
seedtest()
[0.8444218515250481, 0.7579544029403025, 0.420571580830845, 0.25891675029296335, 0.5112747213686085, 0.4049341374504143, 0.7837985890347726, 0.30331272607892745, 0.4765969541523558, 0.5833820394550312]

随机试探

重量和价值如下:
weights = [87,66,70,25,33,24,89,63,23,54]
values = [96,55,21,58,41,81,8,99,59,62]
限定重量:250
试探次数:200
测试有没有最优解。

代码

import random
weights = [87,66,70,25,33,24,89,63,23,54]
values = [96,55,21,58,41,81,8,99,59,62]
N = len(weights)
SEED = 32767 #再打开还有用吗,关机?
R = 10
def solvekp(p,weightlimit,nlimit,N):
    maxvalue = 0
    mweight = 0
    bestp = [0 for i in range(N)]
    for i in range(nlimit):
        rsetp(p,N)
        weight = calcw(p,N)
        if weight <= weightlimit:
            value = calval(p,N)
        else:
            value = 0
        if value >maxvalue:
            maxvalue = value
            mweight = weight
            for j in range(N):
                bestp[j] = p[j]
    print(maxvalue," ",mweight)
    print(bestp)

def calcw(p,N):
    w = 0
    for i in range(N):
        w += weights[i] * p[i]
    return w
def calval(p,N):
    v = 0
    for i in range(N):
        v += values[i]*p[i]
    return v
def rsetp(p,N):
    for i in range(N):
        p[i] = int(random.random()*2)
p = [0 for i in range(N)]
weightlimit = int(input("请输入限定重量:"))
nlimit = int(input("请输入试探次数:"))
random.seed(SEED)
for i in range(R):
    solvekp(p,weightlimit,nlimit,N)

测试

=================== RESTART: C:\Program Files\Python38\rkp.py ==================
请输入限定重量:250
请输入试探次数:200
400   222
[0, 0, 0, 1, 1, 1, 0, 1, 1, 1]
338   168
[0, 0, 0, 1, 1, 1, 0, 1, 1, 0]
359   238
[0, 0, 1, 1, 1, 1, 0, 1, 1, 0]
376   230
[1, 0, 0, 0, 1, 1, 0, 1, 1, 0]
356   213
[1, 0, 0, 1, 0, 1, 0, 0, 1, 1]
393   222
[1, 0, 0, 1, 0, 1, 0, 1, 1, 0]
397   246
[1, 0, 0, 1, 1, 1, 0, 0, 1, 1]
393   222
[1, 0, 0, 1, 0, 1, 0, 1, 1, 0]
393   222
[1, 0, 0, 1, 0, 1, 0, 1, 1, 0]
397   246
[1, 0, 0, 1, 1, 1, 0, 0, 1, 1]
>>> 

从测试结果看,有两百次,有十次是没有超重的。第一个最大价值400就是最优解。

更改限定次数和试探次数测试

=================== RESTART: C:\Program Files\Python38\rkp.py ==================
请输入限定重量:300
请输入试探次数:20
396   253
[1, 0, 0, 1, 0, 1, 0, 1, 0, 1]
371   293
[1, 1, 0, 0, 0, 0, 0, 1, 1, 1]
431   296
[1, 1, 0, 0, 1, 1, 0, 1, 1, 0]
331   235
[1, 1, 0, 1, 1, 1, 0, 0, 0, 0]
397   251
[1, 0, 0, 0, 0, 1, 0, 1, 1, 1]
434   255
[1, 0, 0, 1, 1, 1, 0, 1, 1, 0]
408   297
[1, 1, 0, 1, 1, 0, 0, 1, 1, 0]
362   269
[0, 0, 1, 1, 1, 1, 0, 1, 0, 1]
360   291
[1, 0, 1, 0, 1, 1, 0, 0, 1, 1]
319   198
[0, 0, 0, 1, 1, 0, 0, 1, 1, 1]
>>> 
=================== RESTART: C:\Program Files\Python38\rkp.py ==================
请输入限定重量:200
请输入试探次数:10
193   184
[0, 1, 1, 1, 0, 0, 0, 0, 1, 0]
247   194
[0, 0, 0, 1, 1, 1, 1, 0, 1, 0]
213   152
[0, 1, 0, 0, 0, 0, 0, 1, 1, 0]
235   148
[0, 1, 0, 1, 1, 1, 0, 0, 0, 0]
157   160
[0, 1, 1, 0, 0, 1, 0, 0, 0, 0]
278   165
[0, 0, 0, 1, 0, 0, 0, 1, 1, 1]
198   193
[0, 1, 1, 0, 1, 1, 0, 0, 0, 0]
154   112
[1, 0, 0, 1, 0, 0, 0, 0, 0, 0]
0   0
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
0   0
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
>>> 

贪心算法

排序后只找一遍,不是比较所有解。

    def dictsum(list, keyname):#计算总价值、总重量
        num = 0
        for item in list:
            num += item[keyname]
        return num
            
    class G():
        '''
        每个都做第一次放试探了。
        '''
        def __init__(self, d, m):
            self.m = m
            #self.dl=sorted(self.rd(d),key=lambda x:x.__getitem__("a"),reverse=True)
            self.dl = sorted(self.rd(d), key=lambda x:x["a"], reverse=True) #按单位价低到高排序
            print(self.dl)
            self.sl = [] #选择的解
        def rd(self, d):
            """
            read data
            w for weight
            """
            for i in d:
                v = i["p"] / i["w"]
                i.setdefault("a", v)
            return d
        def pick(self):
            tl = []
            tw = self.m
            for j in range(len(self.dl)):#贪心算法,排序后只找一次,不是比较所有解
                if self.dl[j]["w"] <= tw:#顺序加满一个解
                    tl.append(self.dl[j])
                    tw -= self.dl[j]["w"]
                if [] != tl and dictsum(tl, "p") > dictsum(self.sl, "p"):#剪枝
                    self.sl = tl
            return tl, dictsum(tl,"w"), dictsum(tl,"p")
                        
    d = [{"w":87,"p":96}, {"w":66,"p":55}, {"w":70,"p":21}, {"w":25,"p":58},
         {"w":33,"p":41}, {"w":24,"p":81}, {"w":89,"p":8}, {"w":63,"p":99},
         {"w":23,"p":59}, {"w":54,"p":62},]
    m = 250
    s, sw, sp = G(d, m).pick()
    r = json.dumps([{"select":s, "weight":sw, "price":sp}]) 

打印

计算的单价

[{'w': 24, 'p': 81, 'a': 3.375}, {'w': 23, 'p': 59, 'a': 2.5652173913043477}, {'w': 25, 'p': 58, 'a': 2.32}, {'w': 63, 'p': 99, 'a': 1.5714285714285714}, {'w': 33, 'p': 41, 'a': 1.2424242424242424}, {'w': 54, 'p': 62, 'a': 1.1481481481481481}, {'w': 87, 'p': 96, 'a': 1.103448275862069}, {'w': 66, 'p': 55, 'a': 0.8333333333333334}, {'w': 70, 'p': 21, 'a': 0.3}, {'w': 89, 'p': 8, 'a': 0.0898876404494382}]

选择的物品,从单价高的往下选。

[{"select": [{"w": 24, "p": 81, "a": 3.375}, {"w": 23, "p": 59, "a": 2.5652173913043477}, {"w": 25, "p": 58, "a": 2.32}, {"w": 63, "p": 99, "a": 1.5714285714285714}, {"w": 33, "p": 41, "a": 1.2424242424242424}, {"w": 54, "p": 62, "a": 1.1481481481481481}],

结果

 "weight": 222, "price": 400}]

跟随机算法一样,设置250总重量时,选择的是222重量,400价值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值