例題:dividing
很容易看成乙個多重揹包模型。乙個顯然的做法是直接將問題看成01揹包,然而複雜度無法接受。所謂2k
拆分,基於如下的事實:su
m=20
+21+
22..
.2n+k
加數中若干項的和的取值範圍為且恰好為[1
,sum
]。例如:取1,2和4的情況蘊含了取3,5,6,7的情況,因此不必考慮。至此,只要對於每個num[i],利用列舉將其拆成如上的序列,把每一項看成一件物品進行01揹包即可。
#include
#include
#include
using
namespace
std;
int num[7];
int dp[100001];
int tmp[100001];
int k = 1, tp = 0;
int main() else
}if (num[i] != 0) tmp[++tp] = num[i];
dp[0] = 1;
for (int j = 1; j <= tp; j++)
for (int k = sigma; k >= i*tmp[j]; k--)
dp[k] += dp[k-i*tmp[j]];
}if (dp[sigma/2])
puts("can be divided.\n");
else
puts("can't be divided.\n");}}
return
0;}
例題1:railway tickets
這個題很容易想到1d/1d方程。顯然:如果能用同樣的票價走到更遠的地方,何樂而不為呢?所以轉移的條件是:距離這一站用每種票能走到最遠的一站。由於同種票所能走到的距離是一定的,當dp中所在位置單調時,決策位置也必然單調。因此可以用攤還o(1)的時間找到決策區域,變成了1d/0d方程。不難寫出程式:
注意正反分開討論。
#include
#include
#include
using
namespace
std;
long
long l1,l2,l3,c1,c2,c3;
long
long n, a, b;
long
long f[10005];
long
long dp[10005];
int main()
cout
<< dp[b] << endl;
} else
cout
<< dp[b] << endl;
}return
0;}
例題2:石子合併(經典題)
方程:dp[
i,j]
=max
(dp[
i,k]
,dp[
k+1,
j])+
σa[i
,j]。可以通過構造反證法證明:dp[i,j]取最大值,當且僅當k = i或k = j。這樣就很簡單了。
乙個簡單易行的方法是:用大資料測試優化是否正確。
例題3:oj 9285:盒子與小球之三
一道很典型的dp優化題目。
先變原問題為:從[0,k]中取出m個自然數,使其和為n
dp[i][j]表示[0,k]中取出i個,使其和為j的方案數。很容易寫2d/1d方程(和子集合很像):dp
[i][
j]=∑
kl=0
dp[i
−1][
j−l]
(1)
變形一下:dp
[i][
j−1]
=∑k+
1l=1
dp[i
−1][
j−l]
(2)
(1)-(2),並移項合併得到dp
[i][
j]=d
p[i]
[j−1
]+dp
[i−1
][j]
−dp[
i−1]
[j−k
−1]至此已經轉化為了o(
n2)演算法。至於邊界處理什麼細節很坑qwq,別問我怎麼知道的。
- 可以先處理第一行和第一列,可以省去很多細節判斷;
- 為了防止j-k-1超界,要加一句if (j-k-1 >= 0;
- 負數取模的方法是取模 加模 再取模
#include
#include
#include
using
namespace
std;
int n,m,k;
int dp[5005][5005];
inline
int mod(int x)
int main()
}cout
<< mod(dp[m][n]) << endl;
return
0;}
例題4:花店櫥窗
和3很像,且更簡單,略。
#include
#include
using
namespace
std;
int n, m;
int tab[105][105];
int dp[105][105];
int choose[105];
int main()
for (int i = 1; i <= n; i++)
cout
<< choose[i] << " ";
return
0;}
roads
思路來自《road結題報告,曹利國》。首先查詢不計錢的最短路徑,再查詢不計路程的最小錢。拿這兩個東西做剪枝條件,可以幾乎秒殺。(是否可以證明演算法是多項式的?)
DP動態規劃部分學習總結
這幾天學習動態規劃,我的理解是dp大致可分為2類,一種是自下而上 也叫遞推 另一種是自上而下。這兩種方法都可以達到目的。仔細來講動態規劃是解決多階段決策問題的一種方法。並且每一步得出的結論都講影響下一階段的結果將每一階段都需要取出最佳結果然後一步步下去得出最終答案。並且動態規劃要秉承最優性原理。而最...
寒假集訓小結之動態規劃
time limit 1000 ms memory limit 65536 kib submit statistic problem description 給定乙個由n行數字組成的數字三角形如下圖所示。試設計乙個演算法,計算出從三角形的頂至底的一條路徑,使該路徑經過的數字總和最大。對於給定的由n行...
動態規劃部分題集解
x 星球的考古學家發現了一批古代留下來的密碼。這些密碼是由 a b c d 四種植物的種子串成的序列。仔細分析發現,這些密碼串當初應該是前後對稱的 也就是我們說的映象串 由於年代久遠,其中許多種子脫落了,因而可能會失去映象的特徵。你的任務是 給定乙個現在看到的密碼串,計算一下從當初的狀態,它要至少脫...