嘟嘟嘟
dp。剛開始我想的是dp[i][j]表示在第 i 棵樹上,高度為h能吃到的最多的果子,如此能得到轉移方程: dp[i][j] = max(dp[i][j + 1], dp[k][j + derta]) (k = 1~n && k != i)。但因為這樣寫會導致dp[k][j + derta] (k > i)的部分沒有更新,所以應該把dp試的兩胃交換一下。這樣dp方程就能正常轉移了:
dp[i][j] = max(dp[i + 1][j], max(dp[i + derta][k]) (k = 1~n && k != j) )
然而這樣的時間複雜度是o(h * n * n)的,過不了。
優化:觀察 max(dp[i + derta][k]) (k = 1~n && k != j),實際上我們就是在高度為i + derta 的所有狀態中取乙個max,所以可以開乙個陣列max[i]代表高度為 i 時dp[i][j]的最大值,然後每一次求完dp[i][j]時動態更新max[i]即可。所以轉移方程就變成了
dp[i][j] = max(dp[i +1][j], max[i +derta])
時間複雜度o(h * n)。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8 #include9 #include10 #include11view codeusing
namespace
std;
12#define space putchar(' ')
13#define enter puts("")
14#define mem(a) memset(a, 0, sizeof(a))
15 typedef long
long
ll;16 typedef double
db;17
const
int inf = 0x3f3f3f3f;18
const db eps = 1e-8;19
const
int max_hig = 2e3 + 5;20
const
int maxn = 5e3 + 5;21
inline ll read()
2226
while(isdigit(ch))
27if(last == '
-') ans = -ans;
28return
ans;29}
30 inline void
write(ll x)
3136
37int
n, h, d;
38int
a[max_hig][maxn], dp[max_hig][maxn], max[max_hig];
3940
intmain()
4148
for(int i = h; i >= 0; --i)
49for(int j = 1; j <= n; ++j)
5056
int ans = 0;57
for(int i = 1; i <= n; ++i) ans = max(ans, dp[0
][i]);
58write(ans); enter;
59return0;
60 }
洛谷 P1107 BJWC2008 雷濤的小貓
傳送門 這道題其實是道dpdp dp題,但至於它為什麼會被分到數論,那就不得而知了.首先我們設f i j f i j f i j 為到第i ii高度在第j jj棵樹上時,我們可以摘到的最多柿子數,那麼這時我們可以得到兩個方程 a j i a j i a j i 表示第i ii棵樹的第j jj高度上有...
洛谷 P1107 BJWC2008 雷濤的小貓
給出若干棵樹,以及每棵樹不同高度有幾個柿子的資訊。以及給出走法規則,求能夠獲取到最多的柿子數。我自己的方法是 設dp i j 表示第j棵樹,高度為i時獲得的最大值。然後三重迴圈遍歷一下,第三重迴圈的含義是從之前較高的樹上找出乙個最大的值 乙個最優解 如下 dp計算 for int i h delta...
洛谷P1107 BJWC2008 雷濤的小貓
題目鏈結 n 2dp比較好想,f i j 表示第i棵樹高度為j的最大收益 直接從上到下轉移即可,每次記錄下max f 1 n j 用於下面的轉移 f i j max f i j 1 max f 1 n j delta max f 1 n j delta 是已經求出來的,o 1 查詢 列舉j和i,總複...