原题地址 。
前面,DeepSeek用numpy的线性规划没有解答完成。听张泽鹏先生说他用PuLP这个库整数规划解决了。今天也让DeepSeek编一个。
请用PuLP这个库整数规划解决电压按钮问题,不做别的
他给出了如下程序
import re
import pulp
def parse_line_part2(line):
"""解析一行数据,返回电压要求和按钮列表(第二部分)"""
# 匹配大括号部分
match_brace = re.search(r'\{([^}]+)\}', line)
if not match_brace:
return None, None
# 解析电压要求
joltage_str = match_brace.group(1)
target = [int(x.strip()) for x in joltage_str.split(',')]
# 匹配所有圆括号部分
buttons = []
pattern = r'\(([^)]+)\)'
matches = re.findall(pattern, line)
for match in matches:
# 解析圆括号内的数字
nums = [int(x.strip()) for x in match.split(',')]
buttons.append(nums)
return target, buttons
def solve_machine_pulp(target, buttons):
"""使用PuLP整数规划求解单个机器的电压配置问题"""
n_counters = len(target)
n_buttons = len(buttons)
# 创建整数规划问题
prob = pulp.LpProblem("ButtonPresses", pulp.LpMinimize)
# 创建决策变量(每个按钮的按压次数,非负整数)
x = pulp.LpVariable.dicts('x', range(n_buttons),
lowBound=0, cat='Integer')
# 目标函数:最小化总按压次数
prob += pulp.lpSum([x[i] for i in range(n_buttons)])
# 约束条件:每个计数器的总增加量必须等于目标值
for counter in range(n_counters):
# 计算影响该计数器的所有按钮的总贡献
total_effect = pulp.lpSum([
x[btn_idx] for btn_idx in range(n_buttons)
if counter in buttons[btn_idx]
])
prob += total_effect == target[counter], f"Counter_{counter}_Constraint"
# 求解问题
prob.solve(pulp.PULP_CBC_CMD(msg=False))
# 检查求解状态
if pulp.LpStatus[prob.status] == 'Optimal':
# 提取解
presses_list = [int(pulp.value(x[i])) for i in range(n_buttons)]
total_presses = sum(presses_list)
return total_presses, presses_list, "求解成功"
elif pulp.LpStatus[prob.status] == 'Infeasible':
return -1, None, "无可行解"
else:
return -1, None, f"求解失败: {pulp.LpStatus[prob.status]}"
def validate_solution(target, buttons, presses_list):
"""验证解是否正确"""
if presses_list is None:
return False, None
m = len(target)
current = [0] * m
for j, press_count in enumerate(presses_list):
if press_count > 0:
for idx in buttons[j]:
current[idx] += press_count
return current == target, current
def main():
total_presses = 0
success_count = 0
fail_count = 0
# 读取输入文件
with open('2510-input.txt', 'r') as f:
lines = f.read().strip().splitlines()
for i, line in enumerate(lines):
target, buttons = parse_line_part2(line)
if target is None or not buttons:
continue
min_presses, presses_list, message = solve_machine_pulp(target, buttons)
if min_presses >= 0:
# 验证解
is_valid, calculated = validate_solution(target, buttons, presses_list)
if is_valid:
print(f"机器 {i+1}: {min_presses} 次按压 ({message})")
print(f" 按钮按压次数: {presses_list}")
print(f" 验证通过: {calculated} == {target}")
total_presses += min_presses
success_count += 1
else:
print(f"机器 {i+1}: 验证失败! ({message})")
print(f" 尝试解: {presses_list}")
print(f" 计算值: {calculated} != 目标值: {target}")
fail_count += 1
else:
print(f"机器 {i+1}: 求解失败 ({message})")
fail_count += 1
print(f"\n总结:")
print(f"成功求解: {success_count} 台机器")
print(f"失败: {fail_count} 台机器")
print(f"总最少按压次数: {total_presses}")
return total_presses
if __name__ == "__main__":
main()
安装pulp
python3 pip.pyz install pulp --break-system-packages -i https://pypi.tuna.tsinghua.edu.cn/simple
执行
time python3 2510pulp.txt >2510pulp-res.txt
real 0m0.783s
user 0m0.224s
sys 0m0.056s
cat 2510pulp-res.txt
...
机器 194: 69 次按压 (求解成功)
按钮按压次数: [0, 16, 25, 25, 1, 2]
验证通过: [41, 51, 41, 43] == [41, 51, 41, 43]
机器 195: 37 次按压 (求解成功)
按钮按压次数: [20, 8, 9]
验证通过: [29, 8, 37, 28, 37] == [29, 8, 37, 28, 37]
总结:
成功求解: 195 台机器
失败: 0 台机器
看来问DeepSeek问题不但要说清楚需求,还要说对工具。

379

被折叠的 条评论
为什么被折叠?



