題目描述
眾所周知,牛妹非常喜歡吃蛋糕。
第一天牛妹吃掉蛋糕總數三分之一(向下取整)多乙個,第二天又將剩下的蛋糕吃掉三分之一(向下取整)多乙個,以後每天吃掉前一天剩下的三分之一(向下取整)多乙個,到第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個元素組成的序列即可。...