Python+Excel腳本實(shí)現(xiàn)一鍵生成動(dòng)態(tài)規(guī)劃表
導(dǎo)讀:刷算法題總被“畫DP狀態(tài)表”折磨?手推容易錯(cuò),Excel拉公式又容易串列… 今天分享一段不到50行的Python腳本,從Excel讀取參數(shù) → 自動(dòng)跑完二維DP+一維滾動(dòng)數(shù)組快照 → Pandas一鍵輸出高清報(bào)表。算法黨、數(shù)據(jù)分析師、面試備考者必藏!
為什么“手動(dòng)推演DP”是反 人類設(shè)計(jì)?
動(dòng)態(tài)規(guī)劃(DP)是算法面試的“重災(zāi)區(qū)”,但90%的初學(xué)者都卡在狀態(tài)表推演這一步:
- 紙筆手算:格子一多極易串行,回溯最優(yōu)解直接崩潰
- Excel硬拖:公式嵌套
IF/MAX眼花繚亂,改個(gè)參數(shù)全盤重算 - 純寫代碼:跑完只給個(gè)最終答案,中間狀態(tài)黑盒化,根本不知道“為什么選這個(gè)”
破局思路:把“參數(shù)配置”交給 Excel,把“狀態(tài)推演”交給 Python,把“可視化展示”交給 Pandas。數(shù)據(jù)與邏輯徹底解耦,推演過程透明可追溯!

核心代碼拆解:50行搞定DP全自動(dòng)推演
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
import openpyxl
import pandas as pd
# 1?? 精準(zhǔn)讀取:從 Excel 剝離業(yè)務(wù)參數(shù)
df_items = pd.read_excel("input_data.xlsx", usecols=[0, 1, 2]).dropna()
df_config = pd.read_excel("input_data.xlsx", usecols=[5, 6]).dropna()
item_names = df_items["物品名稱"].tolist()
weights = df_items["物品大小 w[i]"].astype(int).tolist()
values = df_items["物品價(jià)值 v[i]"].astype(int).tolist()
max_capacity = int(df_config.loc[df_config["配置項(xiàng)"] == "最大容量 max_capacity", "參數(shù)值"].values[0])
# 2?? 二維 DP 推演:完整記錄狀態(tài)轉(zhuǎn)移軌跡
n = len(weights)
dp_2d = [[0] * (max_capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
w, v = weights[i - 1], values[i - 1]
for j in range(max_capacity + 1):
if j < w:
dp_2d[i][j] = dp_2d[i - 1][j]
else:
dp_2d[i][j] = max(dp_2d[i - 1][j], dp_2d[i - 1][j - w] + v)
# 3?? 一維滾動(dòng)數(shù)組 + 歷史快照:空間優(yōu)化 O(C),過程全記錄
dp_1d = [0] * (max_capacity + 1)
dp_1d_history = [list(dp_1d)]
for i in range(n):
w, v = weights[i], values[i]
for j in range(max_capacity, w - 1, -1):
dp_1d[j] = max(dp_1d[j], dp_1d[j - w] + v)
dp_1d_history.append(list(dp_1d))
# 4?? Pandas 格式化輸出:告別裸 print,表格即報(bào)表
columns = [str(j) for j in range(max_capacity + 1)]
index_labels = ["無物品"] + item_names
df_2d = pd.DataFrame(dp_2d, index=index_labels, columns=columns)
df_1d = pd.DataFrame(dp_1d_history, index=index_labels, columns=columns)
print(df_2d.to_string())
print(df_1d.to_string())
為什么這段寫法“降維打擊”
二維表 vs 一維快照:教學(xué)與實(shí)戰(zhàn)的完美結(jié)合
dp_2d:保留完整決策樹,適合理解狀態(tài)轉(zhuǎn)移方程dp[i][j] = max(dp[i-1][j], dp[i-1][j-w] + v)dp_1d_history:經(jīng)典空間優(yōu)化O(N×C) → O(C),倒序遍歷防覆蓋。每輪追加list(dp_1d)快照,一眼看清“滾動(dòng)數(shù)組到底怎么滾”,調(diào)試/寫題解直接截圖用。
數(shù)據(jù)讀取“零污染”
df_config.loc[df_config["配置項(xiàng)"] == "最大容量 max_capacity", "參數(shù)值"].values[0]
精準(zhǔn)定位配置單元格,不依賴固定行號(hào)。Excel模板隨便挪,Python照樣抓得準(zhǔn)。
Pandas 一鍵轉(zhuǎn)報(bào)表
index_labels 和 columns 動(dòng)態(tài)生成,索引自帶“無物品”占位,列名直接映射容量 0~max_capacity。輸出結(jié)果可直接 to_excel() 導(dǎo)出,無縫對接匯報(bào)材料。
真實(shí)業(yè)務(wù)能怎么用
| 場景 | DP 映射邏輯 | 業(yè)務(wù)價(jià)值 |
|---|---|---|
| 項(xiàng)目預(yù)算分配 | 容量=總預(yù)算,重量=項(xiàng)目成本,價(jià)值=預(yù)期收益 | 自動(dòng)找出 ROI 最高的項(xiàng)目組合 |
| 倉儲(chǔ)裝載優(yōu)化 | 容量=貨車載重/容積,重量=貨物體積,價(jià)值=運(yùn)費(fèi)/利潤 | 單次發(fā)車?yán)麧欁畲蠡?/td> |
| 服務(wù)器資源調(diào)度 | 容量=CPU/內(nèi)存上限,重量=任務(wù)資源占用,價(jià)值=SLA優(yōu)先級(jí) | 任務(wù)排隊(duì)策略自動(dòng)推演 |
實(shí)戰(zhàn)避坑 & 進(jìn)階玩法
| 坑點(diǎn) | 解決方案 |
|---|---|
| Excel含空行/非數(shù)字字符 | dropna() + .astype(int) 前置清洗 |
| 想看具體選了哪些物品? | 在二維表基礎(chǔ)上加反向回溯邏輯(從 dp[n][C] 逆推) |
| 需要帶高亮樣式的 Excel 報(bào)表? | 代碼已導(dǎo)入 openpyxl.styles,可用 worksheet.cell().fill = PatternFill(...) 給最大值加金色背景 |
| 容量/物品數(shù)超 1000? | 改用 numpy 數(shù)組替代原生 list,內(nèi)存連續(xù)訪問提速 5~10 倍 |
結(jié)語:算法不是玄學(xué),是工程
很多初學(xué)者覺得 DP 抽象,是因?yàn)?strong>缺乏狀態(tài)可視化工具。把參數(shù)抽離到 Excel,把推演交給 Python,把展示交給 Pandas,你不僅是在寫腳本,更是在搭建一套可復(fù)用、可審計(jì)、可交付的算法引擎。
附完整代碼:
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
import openpyxl
import pandas as pd
# ==============================================================================
# 1.輸入?yún)?shù)的 Excel 文件 (input_data.xlsx)
# ==============================================================================
# 在這里原始數(shù)據(jù)表,
input_file = "input_data.xlsx"
# ==============================================================================
# 2. 讀取與計(jì)算階段:完全從 Excel 中加載數(shù)據(jù),并計(jì)算生成最終的 DP 狀態(tài)表
# ==============================================================================
# ---- A. 從 Excel 中讀取數(shù)據(jù) ----
df_read_items = pd.read_excel(input_file, usecols=[0, 1, 2]).dropna()
df_read_config = pd.read_excel(input_file, usecols=[5, 6]).dropna()
# 從讀取到的 DataFrame 中還原出變量列表
item_names = df_read_items["物品名稱"].tolist()
weights = df_read_items["物品大小 w[i]"].astype(int).tolist()
values = df_read_items["物品價(jià)值 v[i]"].astype(int).tolist()
# 從配置區(qū)精準(zhǔn)提取最大容量數(shù)字
max_capacity = int(df_read_config.loc[df_read_config["配置項(xiàng)"] == "最大容量 max_capacity", "參數(shù)值"].values[0])
# ---- B. 核心動(dòng)態(tài)規(guī)劃算法核心邏輯 ----
n = len(weights)
# 1. 計(jì)算二維 DP 狀態(tài)表
dp_2d = [[0] * (max_capacity + 1) for _ in range(n + 1)]
for i in range(1, n + 1):
w, v = weights[i - 1], values[i - 1]
for j in range(max_capacity + 1):
if j < w:
dp_2d[i][j] = dp_2d[i - 1][j]
else:
dp_2d[i][j] = max(dp_2d[i - 1][j], dp_2d[i - 1][j - w] + v)
# 2. 計(jì)算一維滾動(dòng)數(shù)組并截取每輪的歷史快照
dp_1d = [0] * (max_capacity + 1)
dp_1d_history = [list(dp_1d)]
for i in range(n):
w, v = weights[i], values[i]
for j in range(max_capacity, w - 1, -1):
dp_1d[j] = max(dp_1d[j], dp_1d[j - w] + v)
dp_1d_history.append(list(dp_1d))
# ---- C. 使用 Pandas 格式化輸出最終內(nèi)容 ----
columns = [str(j) for j in range(max_capacity + 1)]
index_labels = ["無物品"] + item_names
print("="*43 + " 最終輸出 1:二維 DP 狀態(tài)表 " + "="*43)
df_output_2d = pd.DataFrame(dp_2d, index=index_labels, columns=columns)
df_output_2d.index.name = "物品名稱"
print(df_output_2d.to_string())
print("\n" + "="*41 + " 最終輸出 2:一維滾動(dòng)數(shù)組快照表 " + "="*41)
df_output_1d = pd.DataFrame(dp_1d_history, index=index_labels, columns=columns)
df_output_1d.index.name = "物品名稱"
print(df_output_1d.to_string())
到此這篇關(guān)于 Python+Excel腳本實(shí)現(xiàn)一鍵生成動(dòng)態(tài)規(guī)劃表的文章就介紹到這了,更多相關(guān)Python Excel生成動(dòng)態(tài)規(guī)劃表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用python?dateutil庫輕松處理日期和時(shí)間
這篇文章主要介紹了使用python?dateutil庫輕松處理日期和時(shí)間實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Python使用Plotly Express實(shí)現(xiàn)可視化地理數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Python如何使用Plotly Express實(shí)現(xiàn)可視化地理數(shù)據(jù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-12-12
Python爬蟲模擬登陸嗶哩嗶哩(bilibili)并突破點(diǎn)選驗(yàn)證碼功能
這篇文章主要介紹了Python爬蟲模擬登陸嗶哩嗶哩(bilibili)并突破點(diǎn)選驗(yàn)證碼功能,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
Django框架視圖函數(shù)設(shè)計(jì)示例
這篇文章主要介紹了Django框架視圖函數(shù)設(shè)計(jì),結(jié)合實(shí)例形式分析了Django框架視圖函數(shù)處理流程、原理與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-07-07
Python實(shí)現(xiàn)釘釘自動(dòng)化完整指南
本文詳細(xì)介紹如何使用 Python 實(shí)現(xiàn)釘釘自動(dòng)化,包括消息發(fā)送、部門管理、審批流程觸發(fā)等功能,內(nèi)容涵蓋實(shí)現(xiàn)步驟、前置條件、依賴項(xiàng)以及注意事項(xiàng),幫助快速上手并避免常見問題,需要的朋友可以參考下2025-03-03
Python中的二維數(shù)組實(shí)例(list與numpy.array)
下面小編就為大家分享一篇Python中的二維數(shù)組實(shí)例(list與numpy.array),具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
Python內(nèi)置函數(shù)的用法實(shí)例教程
這篇文章主要介紹了Python內(nèi)置函數(shù)的用法,包括求絕對值的abs()函數(shù)及數(shù)值類型轉(zhuǎn)換函數(shù)等,需要的朋友可以參考下2014-09-09
django實(shí)現(xiàn)圖片上傳數(shù)據(jù)庫并顯示
這篇文章主要為大家詳細(xì)介紹了django實(shí)現(xiàn)圖片上傳數(shù)據(jù)庫并顯示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08

