ABC 209 F - Deforestation
F - Deforestation
插入DP,前缀和优化DP
-
因为砍一颗树的代价只与相邻的树的高度有关,并且在第 \(i\) 棵与第 \(i+1\) 棵中
-
先砍第 \(i\) 棵,代价为 \(h[i-1]+h[i]+h[i+1]+h[i+1]+h[i+2]=h[i-1]+h[i+2]+h[i]+2*h[i+1]\)
-
先砍第 \(i+1\) 棵,代价为
\(h[i]+h[i+1]+h[i+2]+h[i-1]+h[i]=h[i-1]+h[i+2]+2*h[i]+h[i+1]\)
因此相邻两棵树,先砍较高的那棵是最优的
-
-
设 \(f[i][j]\) 为砍掉前 \(i\) 棵树,且第 \(i\) 棵是第 \(j\) 个砍掉的,得到最小代价的方案数
-
\(h[i]<h[i+1]\), 先砍第 \(i+1\) 棵,所以第 \(i\) 棵要在第 \([j+1,i+1]\) 次砍,即第 \(i\) 棵要在前 \(i\) 次中的 \([j,i]\) 次砍
\(f[i+1][j]=\sum\limits_{k=j}^{i}f[i][k]\)
-
\(h[i]>h[i+1]\), 先砍第 $i $ 棵,所以第 \(i\) 棵要在第 \([1,j-1]\) 次砍,即第 \(i\) 棵要在前 \(i\) 次中的 \([1,j-1]\) 次砍
\(f[i+1][j]=\sum\limits_{k=1}^{j-1}f[i][k]\)
-
\(h[i]=h[i+1]\),先砍哪棵都可以
\(f[i+1][j]=\sum\limits_{k=1}^{i}f[i][k]\)
-
-
前缀和优化 DP
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e3 + 10;
const int mod = 1e9 + 7;
int n;
ll f[N][N], sum[N];
ll h[N];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
cin >> h[i];
f[1][1] = sum[1] = 1;
for (int i = 1; i < n; i++)
{
for (int j = 1; j <= i + 1; j++)
{
if (h[i+1] > h[i])
f[i+1][j] = (sum[i] - sum[j-1] + mod) % mod;
else if (h[i+1] < h[i])
f[i+1][j] = sum[j-1];
else
f[i+1][j] = sum[i];
}
for (int j = 1; j <= i + 1; j++)
sum[j] = (sum[j-1] + f[i+1][j]) % mod;
}
ll ans = 0;
for (int i = 1; i <= n; i++)
ans = (ans + f[n][i]) % mod;
cout << ans << endl;
return 0;
}