動態規劃演算法理解 從例題中學習

2021-10-10 12:37:51 字數 3826 閱讀 1988

題目描述
眾所周知,牛妹非常喜歡吃蛋糕。

第一天牛妹吃掉蛋糕總數三分之一(向下取整)多乙個,第二天又將剩下的蛋糕吃掉三分之一(向下取整)多乙個,以後每天吃掉前一天剩下的三分之一(向下取整)多乙個,到第n天準備吃的時候只剩下乙個蛋糕。

牛妹想知道第一天開始吃的時候蛋糕一共有多少呢?

示例1輸入複製2

返回值複製

3思路:

1.(數學分析)首先假設第一天準備開始吃的時候有x份蛋糕,那麼第二天準備開始吃的時候的蛋糕 x-(x*1/3 + 1) = x * 2/3 - 1 份蛋糕。

2.(找狀態方程)設dp[i]為第i天準備開始吃的時候有dp[i]份蛋糕,那麼第二天準備開始吃的時候的蛋糕就為dp[i+1];根據1的分析可得 dp[i+1] = dp[i] * 2/3 - 1;

3.因為題目給定的n代表的是,最後一天她正準備吃的時候剩下的數量,我們要根據這個數量往前推出她第一天的蛋糕數。所以可得方程式dp[i] = 3 * (dp[i+1]+1) / 2; (就是2中的方程變形)。

完事寫**

#include

using

namespace std;

intcakenumber

(int n)

return dp;

}int

main()

題目描述

眾所周知,牛妹有很多很多粉絲,粉絲送了很多很多禮物給牛妹,牛妹的禮物擺滿了地板。

地板是n\times mn×m的格仔,每個格仔有且只有乙個禮物,牛妹已知每個禮物的體積。

地板的座標是左上角(1,1) 右下角(n, m)。

牛妹只想要從屋子左上角走到右下角,每次走一步,每步只能向下走一步或者向右走一步或者向右下走一步

每次走過乙個格仔,拿起(並且必須拿上)這個格仔上的禮物。

牛妹想知道,她能走到最後拿起的所有禮物體積最小和是多少?

思路首先把題目給定的禮物體積存入乙個二維陣列a[max][max]中,然後準備開始動態規劃了。設乙個二維陣列dp[max][max],先初始化計算它的第一行第一列,因為第一行第一列的所有資料只能是通過它的前乙個資料得來,初始完之後,計算其他的。

狀態方程 :dp[i][j] = min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j])) + a[i][j];

就是判斷當前點的向上乙個資料,向左的乙個資料,左上的乙個資料,這三個資料的最小值再加上當前的體積值就是該點的值。

完事寫**

#include

#include

#include

using

namespace std;

#define max 1100

int dp[max]

[max]

,a[max]

[max]

;int

main()

} dp[1]

[1]= a[1]

[1];

for(

int i =

2; i <= n;

++i)

for(

int i =

2; i <= m;

++i)

for(

int i =

2; i <= n;

++i)

} cout << dp[n]

[m];

return0;

}

題目描述

牛牛準備在乙個3行n列的跑道上跑步。一開始牛牛可以自己選擇位於(1,1)還是(2,1)還是(3,1)。

跑道的每一格都有一些金幣,當牛牛跑到乙個格仔,他會獲得這個格仔的所有金幣。

不花費金幣跑到第i行第j+1列

花費m_jmj​

的金幣跑到第i-1行第j+1列(如果i=1則不可以這麼跑)。

花費m_jmj​

的金幣跑到第i+1行第j+1列(如果i=3則不可以這麼跑)。

(牛牛是乙個富豪,本身帶了很多的金幣,所以你不用擔心他錢不夠用)

現在告訴你所有格仔的金幣數量和每一列的金幣花費,牛牛想知道他跑到第n列最多可以賺得多少金幣(賺得金幣=獲得金幣-消耗金幣) 思路

首先用乙個二維陣列a[3][max]把每個格仔的金幣數儲存起來,然後就是初始化dp陣列了。 這個題目的初始化只能初始化dp的第一列,和上一題不同,這個題後面的數都是可以變化的。這題的遍歷只能一列一列的遍歷,不能一行行的來(畫個圖,拿資料推一遍你就知道了。)

狀態方程:

i == 0:(就是比較一下該點左邊和它左下減去跳行的金幣後的大小)

dp[i][j] = max(dp[i][j-1],dp[i+1][j-1] - m[j-1]) + a[i][j];

i == 1:(比較左邊,左上左下減去跳行的金幣後的大小)

dp[i][j] = max(dp[i][j-1],max(dp[i-1][j-1],dp[i+1][j-1])-m[j-1]) + a[i][j];

i == 2:(比較左邊,左上減去跳行的金幣後的大小)

dp[i][j] = max(dp[i][j-1],dp[i-1][j-1] - m[j-1]) + a[i][j];

測試資料

31 9 3

6 4 6

1 1 5

3 2 1

#include

using

namespace std;

#define max 1100

int n;

int a[3]

[max]

,dp[3]

[max]

,m[max]

;int

main()

}for

(int i =

0; i < n;

++i)

dp[0]

[0]= a[0]

[0]; dp[1]

[0]= a[1]

[0]; dp[2]

[0]= a[2]

[0];

for(

int j =

1; j < n;

++j)

else

if(i ==0)

else}}

int t =

-100

;for

(int i =

0; i <3;

++i)

cout << t << endl;

return0;

}

題目描述

牛牛準備在乙個3行n列的跑道上跑步。一開始牛牛位於(1,1)。

跑到第i行第j+1列

跑到第i-1行第j+1列(如果i=1則不可以這麼跑)。

跑到第i+1行第j+1列(如果i=3則不可以這麼跑)。

跑道上有一些格仔設定了路障(乙個格仔可能有多個路障),牛牛不能跑到路障上。現在牛牛想知道,從(1,1)到(3,n)有多少條不同的路徑?

為了防止答案過大,答案對1e9+7取模。

思路跟第三題差不多,dp[i][j] 代表的是該格仔有幾條路可到達。(牛客上是提交核心**)

const

int mod =

1e9+7;

class

solution

dp[1]

[1]=

1; dp[2]

[1]=

0; dp[3]

[1]=

0;for(

int i =

2; i <= n;

++i)

return dp[3]

[n];}}

;

動態規劃演算法理解

幾個月前已經弄懂了的演算法,現在回憶起來這麼費勁。又得重頭開始,真是浪費生命啊。再好的腦袋也不如爛筆頭!這裡用最長公共子串行問題 lcs 來說明演算法 給定兩個序列 x y 求x y長度最長的公共子串行。前期儲備知識 公共子串行不等於公共字串 注意區分 例如,如果x y 那麼就是x和y的公共子串行,...

動態規劃演算法 理解

動態規劃 多階段 兩段 最優化決策解決問題的過程就稱為動態規劃。1 描述優解的結構特徵。2 遞迴地定義乙個最優解的值。3 自底向上計算乙個最優解的值。4 從已計算的資訊中構造乙個最優解。1 最優化原理 問題的最優解包含的字問題也有最優解,就稱該問題具有最優子結構,滿足最優化原理。單調遞增最長子序列 ...

動態規劃演算法例題

題目 有乙個序列 3,5,9,0,2,8,3,9,5,9,2,8 取其中不相鄰子串行,求可能的最大值是多少?思路 用動態規劃來求解。對於最後乙個元素,可以分成兩種情況,取還是不取。如果取,那麼我們在8的基礎上再加上前10個元素組成的序列求得的最大值,如果不取,那麼我們考慮前11個元素組成的序列即可。...