1. 程式人生 > >python -- 0/1揹包問題(動態規劃-list)

python -- 0/1揹包問題(動態規劃-list)

#! /usr/bin/env python3
# -*- coding: utf-8 -*-
'''
	貨物裝箱問題: 每個箱子的尺寸各不相同,你需要儘可能利用每輛卡車的空間,為此你將如何選擇要裝上卡車的箱子呢?
	已知,貨櫃尺寸為RR,箱子的尺寸降序為R[1],R[2],...,R[N],其中N表示箱子總數
	求解:滿足Q = R[1]+...+R[k] <= RR的最大k
	按照貪婪策略得到的不是最優解,舉個栗子:
	RR = 100, R = [50, 40, 30, 20, 5]
	按照貪婪策略:k=2,即 Q = R[1] + R[2] = 50+40 <= 100, R[1]+R[2]+R[3]=120>100
	而最優解應該時R[1]+R[3]+R[4]=50+30+20=100<=100
	類似於揹包問題,採用動態規劃獲取最優解。For i in range(1, RR):更新最大值
'''
'''
	關於旅遊,假設每個旅遊地的旅遊時間以1天為單位,總行程為7天,N個旅遊地,對應的價值為V=V[1],V[2],...,V[N],所需天數為T=T[1],T[2],...,T[N],
	用W = {V[1]:T[1], ... , V[N]:T[N]}
	求解:Q = VMax = V1[1]+...+V1[k] , T1[1]+...+T1[k]<=7, 其中V1[1]---V1[k]為V的子集,T1[1]---T1[k]為對應的T子集, W1 = {V1[1]:T1[1], ... , V1[k]:T1[k]}為W的子集
'''
'''
	集合覆蓋問題:假設你辦了個廣播節目,要讓N個州的聽眾都收聽得到。為此,你需要決定在哪些州廣播臺播出。在儘可能少的廣播臺播出。每個廣播臺都覆蓋特定的區域(州),不同廣播臺的覆蓋區域可能重疊。
	1. 選出這樣一個廣播臺,即它覆蓋了最多的未覆蓋州。
	2. 重複第一步,直到覆蓋所有的州
	採用貪婪策略獲得近似解
'''
# 揹包的容量 capacity
capacity = 4

# 商品的重量和價值
goods = ["音響", "吉他", "筆記本"]
weights = [4, 1, 3]
values = [3000, 1500, 2000]

# 商品的種類數 types
types = len(goods)

def dynamicPlan():
	cell = [ [0 for j in range(capacity+1)] for i in range(types+1) ]
	for i in range(1, types+1):
		for j in range(1, capacity+1):
			cell[i][j] = cell[i-1][j]
			if j >= weights[i-1] and values[i-1]+cell[i-1][j-weights[i-1]] > cell[i][j]:#放得下當前商品,max{當前商品的價值+剩餘容量的價值 , 上一個單元格的值} 
				cell[i][j]=values[i-1]+cell[i-1][j-weights[i-1]]
#	顯示網格
	for i in range(types+1):
		print(cell[i])
	return cell

def pathTrace(cell):
	processed=[False for i in range(types)]
	cap = capacity
	for i in range(types, 0, -1):
		if cell[i][cap] != cell[i-1][cap]:# 從右上角向左下角遍歷
			processed[i-1]=True
			cap-=weights[i-1]
	print(processed)
	print("You choose goods:", end='')
	for i in range(1, types+1):
		if processed[i-1]:
			print("%s, " % goods[i-1], end='')
	print()

if __name__ == "__main__":
	pathTrace(dynamicPlan())