遇到好多問題都在說DPDPDP啊啊啊,好苦惱自己多看看。無非分三步一步一步熟悉就好啦!
原文:http://blog.sina.com.cn/s/blog_50eaa92f0100c8t7.html
動態規划算法的有效性依賴於待求解問題本身具有的兩個重要性質:最優子結構性質和子問題重疊性質。
1、最優子結構性質。如果問題的最優解所包含的子問題的解也是最優的,我們就稱該問題具有最優子結構性質(即滿足最優化原理)。最優子結構性質為動態規划算法解決問題提供了重要線索。
2、子問題重疊性質。子問題重疊性質是指在用遞歸算法自頂向下對問題進行求解時,每次產生的子問題並不總是新問題,有些子問題會被重復計算多次。動態規划算法正是利用了這種子問題的重疊性質,對每一個子問題只計算一次,然后將其計算結果保存在一個表格中,當再次需要計算已經計算過的子問題時,只是在表格中簡單地查看一下結果,從而獲得較高的解題效率。
當我們已經確定待解決的問題需要用動態規划算法求解時,通常可以按照以下步驟設計動態規划算法:
1、分析問題的最優解,找出最優解的性質,並刻畫其結構特征;
2、遞歸地定義最優值;(方便提高邏輯性和節省時間)
3、采用自底向上的方式計算問題的最優值;(自底而上能夠大大減少不必要的重復和提高效率節省時間)
4、根據計算最優值時得到的信息,構造最優解。
1~3步是動態規划算法解決問題的基本步驟,在只需要計算最優值的問題中,完成這三個基本步驟就可以了。如果問題需要構造最優解,還要執行第4步;此時,在第3步通常需要記錄更多的信息,以便在步驟4中,有足夠的信息快速地構造出最優解。
記下DP第一題:hdu1003
http://acm.hdu.edu.cn/showproblem.php?pid=1003
代碼:
#include<stdio.h>
int a[100010];
int dp[100010];
int main()
{
int n,i,t;
int qq=1;
scanf("%d",&t);
while(t--)
{
int start,end,maxu,j1,j2;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
dp[0]=a[0];
j1=j2=start=end=0;
maxu=-100000;
for(i=0;i<n;i++)
{
if(dp[i-1]+a[i]>=a[i])
{
dp[i]=dp[i-1]+a[i];
end=i;
}
else
{
dp[i]=a[i];
start=i;
end=i;
}
if(maxu<dp[i])
{
maxu=dp[i];
j1=start;
j2=end;
}
}
printf("Case %d:\n",qq++);
printf("%d %d %d\n",maxu,j1+1,j2+1);
if(t!=0)
printf("\n");
}
}
