簡單的區間 dp

2021-07-09 17:36:51 字數 1518 閱讀 8513

今天我們來一起研究一下比較奇怪的區間dp

先看一道例題

石子合併 很老的題了

1960: 石子合併

time limit: 1 sec memory limit: 128 mb

submit: 191 solved: 78

[submit][status][web board]

description

在乙個圓形操場的四周擺放著n 堆石子。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2 堆石子合併成新的一堆,並將新的一堆石子數記為該次合併的得分。

試設計乙個演算法,計算出將n堆石子合併成一堆的最小得分和最大得分。

input

包含兩行,第1 行是正整數n(1<=n

<=100),表示有n堆石子。

第2行有n個數,分別表示每堆石子的個數。

output

輸出兩行。

第1 行中的數是最小得分;第2 行中的數是最大得分。

sample

input44

459sample

output

4354

01.暴力搜尋,我不相信你拿不到部分分......

02.暴力列舉 0102混合使用,效果更佳

03.區間dp

這是一種非常高效的做法我們不妨用dp[i][j]來表示從第i堆(包含i)到第j堆(包含j)石子的合併的最大代價

還要利用sum[i]做乙個字首和作為輔助

轉移方程為:dp[i][j]=maxmize * k從i到j(不包含j)*(最小的也一樣 自己yy)

len=2表示第一次合併的情況,此時合併的石子為2堆。此時,i從1到n-len+1,j=i+len-1

為了使我們進行的更為便捷,我們還需要進行乙個簡單的優化

即將複雜的環轉化簡單的鏈 這是一種十分有效的方法 用空間來換取操作上的簡便

為了方便大家的理解 我把自己的**給大家 並不好看……..

#include //看不慣的不要噴.....

using namespace std;

int a[205],f1[205][205],f2[205][205],sum[205];//最大 最小 字首和

inline int read()

while (ch >= '0' && ch <= '9')

return x * f;

}int main()

for(int i= n+1;i<= 2*n;i++)

for(int i = 1;i<= 2*n-1;i++)

for(int len = 3;len<= n;len++)}}

int minx = 0x3f3f3f,maxx = 0;

for(int i = 1;i<= n;i++)

printf("%d\n%d",minx,maxx);

return

0;}

POJ 3280 簡單區間 DP

就是想的時候不要想漏了轉移方式。對於乙個回文串 去掉最左和最右兩個後依然是回文串,好了。dp 轉移有三種,一種是從 dp i 1 j 轉移過來,一種是從 dp i j 1 轉移過來,一種是從 dp i 1 j 1 轉移過來 include include include include includ...

區間DP例題總結 看似不簡單的簡單題

今天,我們開始學那奇怪的區間dp。簡單來說,區間dp分為三個部分 階段列舉左端點,再列舉右端點 策略 顧名思義就是因為有些題,需要求出中點k,但有些題卻又不需要。所以我們應該判斷,用與不用。現在我們來看幾道經典例題 n堆石子擺成一條線。現要將石子有次序地合併成一堆。規定每次只能選相鄰的2堆石子合併成...

線性dp 區間dp

1 尼克的任務 額一道挺水的題,愣是做了幾個小時 動態規劃大致的思路還是找乙個轉移 換個詞就是影響 我們可以明顯看出本題的規則 空暇時,一遇到任務必須挑乙個接 求1 n時間內最大空暇時間 所以將任務排序是必要的,兩個關鍵字 再來想象一下當我做到第i 個任務時,我在 st i st i t i 1 時...