201971010135-孙得弘 实验二 个人项目——《0-1背包问题》项目报告
项目 | 内容 |
---|---|
课程班级博客链接 | 2019卓越班 |
这个作业要求链接 | 作业要求链接 |
我的课程学习目标 | (1)掌握软件项目个人开发流程(2)掌握Github发布软件项目的操作方法。 |
这个作业在哪些方面帮助我实现学习目标 | (1)掌握了psp流程(2)复习了0-1背包问题(3)学习了GitHub |
项目Github的仓库链接地址 | 仓库地址 |
作业点评的链接
点评1:李治江
点评2:李斌
点评3:姚恪
项目实施
项目分析
需求分析
{0-1}KP数据集是研究{0-1}背包问题时,用于评测和观察设计算法性能的标准数据集;动态规划算法、回溯算法是求解{0-1}背包问题的经典算法。查阅相关资料,设计一个采用贪心算法、动态规划算法、回溯算法求解{0-1}背包问题的程序,程序基本功能要求如下:
1.可正确读入实验数据文件的有效{0-1}KP数据;
2.能够绘制任意一组{0-1}KP数据以价值重量为横轴、价值为纵轴的数据散点图;
3.能够对一组{0-1}KP数据按重量比进行非递增排序;
4.用户能够自主选择贪心算法、动态规划算法、回溯算法求解指定{0-1} KP数据的最优解和求解时间(以秒为单位);
5.任意一组{0-1} KP数据的最优解、求解时间和解向量可保存为txt文件或导出EXCEL文件。
根据题目要求我们首先可以确定的是需要用的三种数据结构来完成,分别是动态规划法,回溯法,贪心算法,并且用户可以自行选择求解方案,得出最优解和求解时间。在题目中并没有规定所使用的语言,所有我们可以选择我们擅长的语言进行代码的编写。所以我先要去复习算法设计中贪心法,回溯法以及动态规划法的0-1背包问题
功能设计
基本功能:
- 读取文件数据:可正确读入实验数据文件的有效D{0-1}KP数据;
- 绘制散点图:绘制任意一组D{0-1}KP数据以重量为横轴、价值为纵轴的数据散点图;
- 排序:对一组D{0-1}KP数据按项集第三项的价值:重量比进行非递增排序;
- 求解最优解和时间:求解指定D{0-1} KP数据的最优解和求解时间(以秒为单位);
- 将数据结果保存为txt文件:将一组D{0-1} KP数据的最优解、求解时间和解向量保存为txt文件;
设计实现
- 本次设计使用到主要的函数分别为围绕着三种核心算法,有GreedyAlgo函数,Dynamic函数,backtrack函数,他们分别实现了贪心算法,动态规划算法以及回溯算法。
- 为了实现本次设计还需引入python中time,numpy,matplotlib.pyplot等模块分别来实现程序运行时间统计,二维数组控制,以及绘制散点图。
- 运用with open的方法可以将我们所需要的数据以txt文件格式保存
- 本次设计主要是面向流程的程序设计思路,同时也夹杂了一些面向对象的程序设计,由于本人对于对象的操作还是不够熟练,所以整体代码的风格显得有些繁琐,下面给出整体设计流程图
graph TD
A[开始] --> B(选择求解方案)
B --> C{输入1,2,3}
C --> |n=1| D[贪心法] --> G[最优解] --> H[绘制散点图以及求解时间] --> I[结束]
C --> |n=2| E[动态规划法] --> G
C --> |n=3| F[回溯法] --> G
测试运行
- 输入测试数据
- 非递增排序以及最优解
- 散点图
- 最终结果以及运行时间
- 生成的txt文件
代码展示
贪心法函数代码
def GreedyAlgo(item, weight_most, idex):
number = len(item)
status = [0] * number
total_weight = 0
total_value = 0
for i in range(number):
if item[idex[i], 0] <= weight_most:
total_weight += item[idex[i], 0]
total_value += item[idex[i], 1]
status[idex[i]] = 1
weight_most -= item[idex[i], 0]
else:
continue
return total_weight, total_value, status
动态规划法函数代码
def Dynamic(weight, value, weight_most): # return max value
num = len(weight)
weight.insert(0, 0) # 前0件要用
value.insert(0, 0) # 前0件要用
bag = np.zeros((num + 1, weight_most + 1), dtype=np.int32) # 下标从零开始
for i in range(1, num + 1):
for j in range(1, weight_most + 1):
if weight[i] <= j:
bag[i][j] = max(bag[i - 1][j - weight[i]] + value[i], bag[i - 1][j])
else:
bag[i][j] = bag[i - 1][j]
# print(bag)
return bag[-1, -1]
回溯法函数代码
def backtrack(i):
global bestV, curW, curV, x, bestx
if i >= n:
if bestV < curV:
bestV = curV
bestx = x[:]
else:
if curW + weight[i] <= weight_most:
x[i] = True
curW += weight[i]
curV += value[i]
backtrack(i + 1)
curW -= weight[i]
curV -= value[i]
x[i] = False
backtrack(i + 1)
散点图绘制代码
print("是否打印散点图?")
m = input()
if m=='y' or 'Y':
plt.figure(figsize=(10, 10), dpi=100)
plt.scatter(weight[1:],value[1:])
plt.show()
if m=='n' or 'N':
pass
总结
- 我对于软件设计的“模块化”原则的实现是在面向过程的程序设计基础上将代码大致分为三个大的模块,分别对应01背包问题的三种算法,然后在这三个模块中又有各自对应的功能函数,由于我代码水平有限在三个模块中有很多重复的地方,这些应该都是可以优化的地方。
PSP展示
耗时最多的是开发阶段的代码编写部分,由于我的基础不是很扎实,对于动态规划法和回溯法的具体步骤已经遗忘所以花费了大量时间进行重新学习。而代码编写对于我也是一项薄弱环节,所以花费的时间大量超出了预计时间。
心得体会
- 通过这次个人项目我体会到了软件工程这门学科的基本意义,同时也理解了一个人的力量是很有限的,如果是开发一个复杂一些的项目仅凭借一个人的力量是很难完成的。通过这次项目我也发现了很多自身的不足包括代码能力弱,基础算法掌握不牢靠等问题。在这次实验中我学习了很多python的新功能,让我更加体会到了python语言的优势与强大,在今后的学习中我要继续提高自己的编码能力以及软件工程项目开发的能力。