開場先來一段百度百科:ios
動態規劃中本階段的狀態每每是上一階段狀態和上一階段決策的結果。若是給定了第K階段的狀態Sk以及決策uk(Sk),則第K+1階段的狀態Sk+1也就徹底肯定。也就是說Sk+1與Sk,uk之間存在一種明確的數量對應關係,記爲Tk(Sk,uk),即有Sk+1= Tk(Sk,uk)。 這種用函數表示先後階段關係的方程,稱爲狀態轉移方程。在上例中狀態轉移方程爲 Sk+1= uk(Sk) 。數組
poj1018題意:函數
目前有一個公司須要購進寬帶設備,每種設備有多款機器供選擇,每種設備都需購進一臺,現給出每臺設備的帶寬p與價格q,要求選擇設備的最小帶寬min(p)/add(q)(其中min(p)表示全部購進設備中最小的帶寬,add(q)表示全部購進設備的價格之和)爲最大,並求出該值。測試
輸入:spa
第一行表示測試用例個數與設備種類數code
接下來每一行第一個數表示每種設備有多少款機器,後面緊跟每款機器的帶寬與價格。blog
題目讀完,仍是強調直覺,這題可以使用動態規劃得解;ci
分析動態規劃關鍵點:get
很是明顯這個問題能夠進行分解,分解以下:it
設dp[i][j]爲前i組帶寬爲j的最小价格和,那麼狀態轉移方程爲dp[i][j]=min{dp[i][j] , dp[i-1][k]+q},表示dp[i][j]爲在兩種狀況中取最小值:
1.j正好爲最小帶寬,dp[i][j]就爲前i組帶寬爲j的價格和
2.以前的帶寬k爲最小帶寬,價格爲以前價格再加上q
代碼以下:
#include<iostream> #include<algorithm> using namespace std; const int inf = 0x3f3f3f3f; int a[120][1100]; //狀態轉移方程:dp[i][j] = min( dp[i][j] , dp[i-1][k]+q ) //dp[i][j]表示前i組帶寬爲j的最小价格 int main(){ int n; cin>>n; while(n--){ int m; cin>>m; for(int i=1;i<=m;i++){ for(int j=0;j<1100;j++){ a[i][j]=inf; } } for(int i=1;i<=m;i++){ int num; cin>>num; for(int j=0;j<num;j++){ int p,q; cin>>p>>q; if(i==1){ a[i][p]=min(a[1][p],q); }else{ //之因此從0遍歷到1200: //1.預估帶寬最大到1200 //2.保證全部的帶寬與對應的最小价格都被存到二維數組中,最後所求最小价格即爲a[3][min帶寬] for(int k=0;k<1100;k++){ if(a[i-1][k]!=inf){ if(k<=p){ a[i][k]=min(a[i][k],a[i-1][k]+q); }else{ a[i][p]=min(a[i][p],a[i-1][k]+q); } } } } } } double res=0; for(int i=0;i<1100;i++){ if(a[m][i]!=inf){ double temp = (double)i/a[m][i]; if(temp>res){ res=temp; } } } printf("%.3lf\n",res); } return 0; }