题意
n n n棵树,砍掉第 i i i棵树的代价是 H i + H i − 1 + H i + 1 H_i+H_{i-1}+H_{i+1} Hi+Hi−1+Hi+1,之后 H i H_i Hi变为 0 0 0
砍掉这 n n n课树有 n ! n! n!种砍树顺序,问有多少种是最小代价的砍树方案.
怎样砍树是最优的?
现在只考虑第 i i i棵树和第 i + 1 i+1 i+1棵树带来的代价
若第 i i i棵树先被砍,那么此时代价为 H i + 2 ∗ H i + 1 H_i+2*H_{i+1} Hi+2∗Hi+1
若第 i + 1 i+1 i+1棵树先被砍,那么此时代价为 2 ∗ H i + H i + 1 2*H_i+H_{i+1} 2∗Hi+Hi+1
得到结论若 H i < H i + 1 H_i<H_{i+1} Hi<Hi+1,先砍第 i + 1 i+1 i+1棵树
若 H i > H i + 1 H_i>H_{i+1} Hi>Hi+1,先砍第 i i i棵树
定义 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i个棵树中第 i i i棵是第 j j j次被砍掉的最小代价
当 H i < H i + 1 H_i<H_{i+1} Hi<Hi+1,意味着 i + 1 i+1 i+1位置需要先放,有转移
f [ i + 1 ] [ j ] = ∑ k = j i f [ i ] [ k ] f[i+1][j]=\sum\limits_{k=j}^i f[i][k] f[i+1][j]=k=j∑if[i][k]
当 H i > H i + 1 H_i>H_{i+1} Hi>Hi+1,意味着 i i i位置需要先放,有转移
f [ i + 1 ] [ j ] = ∑ k = 1 j − 1 f [ i ] [ k ] f[i+1][j]=\sum\limits_{k=1}^{j-1} f[i][k] f[i+1][j]=k=1∑j−1f[i][k]
当 H i = H i + 1 H_i=H_{i+1} Hi=Hi+1,什么先后顺序都无所谓,有转移
f [ i + 1 ] [ j ] = ∑ k = 1 i f [ i ] [ k ] f[i+1][j]=\sum\limits_{k=1}^{i} f[i][k] f[i+1][j]=k=1∑if[i][k]
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod = 1e9+7;
const int maxn = 5009;
int n,h[maxn],f[maxn][maxn],sum[maxn];
signed main()
{
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;
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;
}
int ans = 0;
for(int i=1;i<=n;i++) ans = ( ans+f[n][i] )%mod;
cout << ( ans%mod+mod )%mod;
return 0;
}