ybt1675塔
1675:塔
时间限制: 1000 ms 内存限制: 262144 KB
【题目描述】
你有\(N\)座塔一列排开。每座塔各自有高度,有可能相等。
你每次可以选择相邻的两座塔合并在一起,即这两座塔的高度叠加后变成了同一座塔。然后原本分别与这两座塔相邻的塔变得与这座新的塔相邻。
你的目标是使用最少的操作次数在游戏的最后获得一列塔,这些塔的高度从左到右形成一个不下降的数列。
【输入】
第一行一个整数\(N\)。
第二行\(N\)个整数,从左到右描述塔的高度。
【输出】
仅一个整数表示最少的操作次数。
【输入样例】
5
8 2 7 3 1
【输出样例】
3
【数据规模】
对于30%的数据,\(N≤10\)。
对于60%的数据,\(N,A_i≤200\)。
对于100%的数据,\(1≤N,A_i≤3000\)。
动态规划。据说可以单调优化,以后再说……
f[i]:前i个塔单调不下降最少的操作次数
mn[i]:对应f[i]的最后一个的高度
f[n]就是答案了
#include<bits/stdc++.h>
using namespace std;
const int maxn=3010;
int n,sz[maxn];
int f[maxn],mn[maxn];
int main()
{
scanf("%d",&n);
for(int a,i=1;i<=n;++i)scanf("%d",&a),sz[i]=sz[i-1]+a;
memset(f,0x7f,sizeof f);f[0]=0;
for(int i=1;i<=n;++i)
{
for(int j=i-1;j>=0;--j)
if(sz[i]-sz[j]>=mn[j])
if(f[j]+i-j-1<f[i])
{
f[i]=f[j]+i-j-1;
mn[i]=sz[i]-sz[j];
}
}
cout<<f[n]<<endl;
return 0;
}