题意是:每次操作能将某个数加到隔壁的数上面,最后求最少操作数,使得序列是非递减序列。
思路:我们发现每次可以将l~r之间的区间合并成一个数,然后需要r-l次操作,我们设定从f[i]为从1处理到i并且序列是递增的最少操作数,然后枚举i是在哪一段区间里,维护l[i](在不影响f[i]最优值的情况下l[i]最小的可能高度)因为小的高度容易让后面接嘛。
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N=5010;
#define debug() cout<<"---"<<endl;
int h[N];
int n;
int f[N];//考虑前i个塔的最小操作数
int minv[N];
int s[N];
int main()
{
cin >> n;
for(int i=1;i<=n;i++)
cin>>h[i];
memset(f,0x3f,sizeof f);
memset(minv,0x3f,sizeof minv);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+h[i];
f[1]=0;
f[0]=0;
minv[0]=0;
minv[1]=h[1];
for(int i=2;i<=n;i++)
{
for(int j=1;j<=i;j++)
if(s[i]-s[j-1]>=minv[j-1] && f[i]>=f[j-1]+(i-j))//将i~j合并
{
f[i]=f[j-1]+i-j;
minv[i]=min(minv[i],s[i]-s[j-1]);
}
}
cout<<f[n]<<endl;
return 0;
}