0-1背包问题——回溯法求解【Python】
回溯法求解0-1背包问题:
问题:背包大小 w,物品个数 n,每个物品的重量与价值分别对应 w[i] 与 v[i],求放入背包中物品的总价值最大。
回溯法核心:能进则进,进不了则换,换不了则退。(按照条件深度优先搜索,搜到某一步时,发现不是最优或者达不到目标,则退一步重新选择)
注:理论上,回溯法是在一棵树上进行全局搜索,但是并非每种情况都需要全局考虑,毕竟那样效率太低,且通过约束+限界可以减少好多不必要的搜索。
解决本问题思路:使用0/1序列表示物品的放入情况。将搜索看做一棵二叉树,二叉树的第 i 层代表第 i 个物品,若剩余空间允许物品 i 放入背包,扩展左子树。若不可放入背包,判断限界条件,若后续继续扩展有可能取得最优价值,则扩展右子树(即此 i 物品不放入,但是考虑后续的物品)。在层数达到物品的个数时,停止继续扩展,开始回溯。
注:如何回溯呢?怎样得到的,怎样恢复。放入背包中的重量取出,加在bagV上的价值减去。
约束条件:放入背包中物品的总质量小于等于背包容量
限界条件:当前放入背包中物品的总价值(i及之前) + i 之后的物品总价值 < 已知的最优值 这种情况下就没有必要再进行搜索
数据结构: 用一个变量记录当前放入背包的总价值 bagV(已扩展),一个变量记录后续物品的总价值 remainV(未扩展),当前已得到的一种最优值 bestV(全局情况),一个用0/1表示的数组bestArr[]记录哪些物品放入了背包。
核心结构:递归思路进行解决。层层递归,递归到尽头,保留最优值,恢复递归中,层层回溯,即将原来加上去的重量与价值恢复。
# -*- coding:utf-8 -*- def Backtrack(t):
global bestV, bagW, bagV,arr, bestArr, cntV if t > n: #某次深度优先搜索完成
if bestV < bagV:
for i in range(1, n+1):
bestArr[i] = arr[i]
bestV = bagV
else: #深度优先搜索未完成
if bagW + listWV[t][0] <= w: #第t个物品可以放入到背包中,扩展左子树
arr[t] = True
bagW += listWV[t][0]
bagV += listWV[t][1]
Backtrack(t+1)
bagW -= listWV[t][0]
bagV -= listWV[t][1]
if cntV[t] + bagV > bestV: #有搜索下去的必要
arr[t] = False
Backtrack(t+1) if __name__ == '__main__': w = int(input()) #背包大小
n = int(input()) #物品个数 listWV = [[0,0]]
listTemp = []
sumW = 0
sumV = 0 for i in range(n):
listTemp = list(map(int, input().split())) #借助临时list每次新增物品对应的list加入到listWV中
sumW += listTemp[0]
sumV += listTemp[1]
listWV.append(listTemp) #依次输入每个物品的重量与价值 bestV = 0
bagW = 0
bagV = 0
remainV = sumV
arr = [False for i in range(n+1)]
bestArr = [False for i in range(n+1)] cntV = [0 for i in range(n+1)] #求得剩余物品的总价值,cnt[i]表示i+1~n的总价值
cntV[0] = sumV
for i in range(1, n+1):
cntV[i] = cntV[i-1] - listWV[i][1] if sumW <= w:
print(sumV)
else:
Backtrack(1)
print(bestV)
print(bestArr)
print(cntV)
检测:
10
5
2 6
5 3
4 5
2 4
3 6 17
[False, True, False, True, False, True]
[24, 18, 15, 10, 6, 0]
0-1背包问题——回溯法求解【Python】的更多相关文章
- 01背包问题(回溯法)python实现
接上一篇,相同的01背包问题,上一篇採用动态规划的方法,如今用回溯法解决. 回溯法採用深度优先策略搜索问题的解.不多说.代码例如以下: bestV=0 curW=0 curV=0 bestx=None ...
- 算法——八皇后问题(eight queen puzzle)之回溯法求解
八皇后谜题是经典的一个问题,其解法一共有种! 其定义: 首先定义一个8*8的棋盘 我们有八个皇后在手里,目的是把八个都放在棋盘中 位于皇后的水平和垂直方向的棋格不能有其他皇后 位于皇后的斜对角线上的棋 ...
- USACO 1.5.4 Checker Challenge跳棋的挑战(回溯法求解N皇后问题+八皇后问题说明)
Description 检查一个如下的6 x 6的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行,每列,每条对角线(包括两条主对角线的所有对角线)上都至多有一个棋子. 列号 0 1 2 3 4 5 6 ...
- 回溯法求解n皇后和迷宫问题
回溯法是一种搜索算法,从某一起点出发按一定规则探索,当试探不符合条件时则返回上一步重新探索,直到搜索出所求的路径. 回溯法所求的解可以看做解向量(n皇后坐标组成的向量,迷宫路径点组成的向量等),所有解 ...
- 0-1背包问题蛮力法求解(c++版本)
// 0.1背包求解.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #define ...
- 0-1背包问题蛮力法求解(java版本)
sloves: package BackPack; public class Solves { public int[] DecimaltoBinary(int n,int m) { int ...
- 回溯法——求解N皇后问题
问题描写叙述 八皇后问题是十九世纪著名数学家高斯于1850年提出的.问题是:在8*8的棋盘上摆放8个皇后.使其不能互相攻击,即随意的两个皇后不能处在允许行.同一列,或允许斜线上. 能够把八皇后问题拓展 ...
- n皇后问题(回溯法)——Python实现
八皇后问题 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子.皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子.在一个棋盘上如果要放八个皇后,使得她们互 ...
- Java实现动态规划法求解0/1背包问题
摘要: 使用动态规划法求解0/1背包问题. 难度: 初级 0/1背包问题的动态规划法求解,前人之述备矣,这里所做的工作,不过是自己根据理解实现了一遍,主要目的还是锻炼思维和编程能力,同时,也是为了增进 ...
随机推荐
- Leetcode: Campus Bikes II
On a campus represented as a 2D grid, there are N workers and M bikes, with N <= M. Each worker a ...
- linux安装上传下载工具lrszs
普通用户下使用sudo获取root权限,root用户直接安装: [mall@VM_0_7_centos ~]$ sudo yum -y install lrzsz Loaded plugins: fa ...
- linux无网络情况下安装rpm包
首先理清楚两个东西:rpm和yum.rpm全称redhat package manager,用来管理软件包:yum全称yellow dog updater,modified,它是rpm的前端程序,因为 ...
- ES6深入浅出-4 迭代器与生成器-3.生成器 & for...of
迭代器平时用的很少.但是如果你是写框架的,你会经常用到迭代器. 生成器是专门用来做迭代器的东西 发布器是要产生一个叫做next的对象,如果你要产生这种对象.就可以使用ES6新出的语法. ES6的新语法 ...
- Hadoop记录-HDFS均衡脚本
#!/bin/bash #作用:hdfs使用率取最大100个主机和最小80个主机进行数据均衡 #打印报告 hdfs dfsadmin -report>report.txt #截取主机名 cat ...
- 宣化上人:大佛顶首楞严经四种清净明诲浅释(4-5)(转自学佛网:http://www.xuefo.net/nr/article23/230699.html)
大佛顶首楞严经四种清净明诲浅释(4) 唐天竺·沙门般剌密帝译 宣化上人主讲 一九八三年四月十七日晚讲于万佛圣城 汝教世人修三摩地.先断心淫.是名如来.先佛世尊.第一决定清净明诲. 所以说,教人这个爱的 ...
- python通过socket实现多个连接并实现ssh功能详解
python通过socket实现多个连接并实现ssh功能详解 一.前言 上一篇中我们已经知道了客户端通过socket来连接服务端,进行了一次数据传输,那如何实现客户端多次发生数据?而服务端接受多个客户 ...
- LeetCode_242. Valid Anagram
242. Valid Anagram Easy Given two strings s and t , write a function to determine if t is an anagram ...
- Java基础教程:多线程杂谈——双重检查锁与Volatile
Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...
- WebException 请求被中止: 操作超时
HTTP 请求时出现 :WebException 请求被中止: 操作超时 处理HTTP请求的服务器 CPU 100% ,重启后正常.