ABC 209 F - Deforestation

F - Deforestation

插入DP,前缀和优化DP

  1. 因为砍一颗树的代价只与相邻的树的高度有关,并且在第 i 棵与第 i+1 棵中

    1. 先砍第 i 棵,代价为 h[i1]+h[i]+h[i+1]+h[i+1]+h[i+2]=h[i1]+h[i+2]+h[i]+2h[i+1]

    2. 先砍第 i+1 棵,代价为

      h[i]+h[i+1]+h[i+2]+h[i1]+h[i]=h[i1]+h[i+2]+2h[i]+h[i+1]

    因此相邻两棵树,先砍较高的那棵是最优的

  2. f[i][j] 为砍掉前 i 棵树,且第 i 棵是第 j 个砍掉的,得到最小代价的方案数

    1. h[i]<h[i+1], 先砍第 i+1 棵,所以第 i 棵要在第 [j+1,i+1] 次砍,即第 i 棵要在前 i 次中的 [j,i] 次砍

      f[i+1][j]=k=jif[i][k]

    2. h[i]>h[i+1], 先砍第 i 棵,所以第 i 棵要在第 [1,j1] 次砍,即第 i 棵要在前 i 次中的 [1,j1] 次砍

      f[i+1][j]=k=1j1f[i][k]

    3. h[i]=h[i+1],先砍哪棵都可以

      f[i+1][j]=k=1if[i][k]

  3. 前缀和优化 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;
}
posted @   hzy0227  阅读(59)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示