《程序员的算法趣题》-(日)增井敏克 , 书中为69 道数学谜题编写了解题程序, 编程语言为:Ruby(为主),JavaScript,C语言。有兴趣的同学,可以购书阅读~
在此更新个人编写的Python版,仅供学习使用。(运行环境:Python3.6)
Q28 社团活动的最优分配方案
对学生而言,社团活动可能比学习还更重要。假设你即将成为某新建学校的校长,学校里有150 名想要运动的学生,请
你考虑要为他们准备哪些社团活动。
你调查各项运动所需的场地面积后得到了如表所示的表格。在确定活动场地时,也要考虑各个社团的人数。
问题
请选择一些社团活动,社团总人数不能超过 150 人,还要使场地面积最大。求这个最大的面积的值。
分三种写法完成此题,各有优势。
group_info = [(11000, 40),
(8000, 30),
(400, 24),
(800, 20),
(900, 14),
(1800, 16),
(1000, 15),
(7000, 40),
(100, 10),
(300, 12)]
# 最简单,递归
MAX_AREA = 0
def calculate(res_group, people, area):
for group in res_group:
if group[1] + people > 150:
global MAX_AREA
MAX_AREA = max(MAX_AREA, area)
else:
new_res_group = res_group[:]
new_res_group.remove(group)
calculate(new_res_group, group[1]+people, area+group[0])
calculate(group_info, 0, 0)
print("最大的面积的值:%s" % MAX_AREA)
# 动态加载
from copy import deepcopy
number_area = {0: 0}
for group in group_info:
old_number_area = deepcopy(number_area)
for number in old_number_area:
new_number = number + group[1]
new_area = old_number_area[number]+group[0]
if new_number <= 150:
if new_number in number_area:
number_area[new_number] = max(old_number_area[new_number], new_area)
else:
number_area[new_number] = new_area
print("最大的面积的值:%s" % max(number_area.values()))
# 内存化
calculated_map = {}
def calculate(res_people, res_group):
if res_people < 0 or len(res_group) == 0:
return 0
elif (res_people, tuple(res_group)) in calculated_map:
return calculated_map[(res_people, tuple(res_group))]
max_area = 0
for group in res_group:
if group[1] <= res_people:
new_res_group = res_group[:]
new_res_group.remove(group)
max_area = max(group[0] + calculate(res_people-group[1], new_res_group), max_area)
calculated_map[(res_people, tuple(res_group))] = max_area
return max_area
print("最大的面积的值:%s" % calculate(150, group_info))
运行结果:
最大的面积的值:28800