# codeforces 229/D 动态规划

D. Towers
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

The city of D consists of n towers, built consecutively on a straight line. The height of the tower that goes i-th (from left to right) in the sequence equals hi. The city mayor decided to rebuild the city to make it beautiful. In a beautiful city all towers are are arranged in non-descending order of their height from left to right.

The rebuilding consists of performing several (perhaps zero) operations. An operation constitutes using a crane to take any tower and put it altogether on the top of some other neighboring tower. In other words, we can take the tower that stands i-th and put it on the top of either the (i - 1)-th tower (if it exists), or the (i + 1)-th tower (of it exists). The height of the resulting tower equals the sum of heights of the two towers that were put together. After that the two towers can't be split by any means, but more similar operations can be performed on the resulting tower. Note that after each operation the total number of towers on the straight line decreases by 1.

Help the mayor determine the minimum number of operations required to make the city beautiful.

Input

The first line contains a single integer n (1 ≤ n ≤ 5000) — the number of towers in the city. The next line contains n space-separated integers: the i-th number hi (1 ≤ hi ≤ 105) determines the height of the tower that is i-th (from left to right) in the initial tower sequence.

Output

Print a single integer — the minimum number of operations needed to make the city beautiful.

Sample test(s)
input
5
8 2 7 3 1

output
3

input
3
5 2 1

output
2


#include <bits/stdc++.h>
using namespace std;
int dp[5002][5002];//第i个塔，用了j步骤的高度,向前压，向后压
const int inf=0x7f7f7f7f;
class Solution
{
int n,a[5002];
public:
Solution(int _n):n(_n)
{
for(int i=0; i<n; ++i)
scanf("%d",&a[i]);
memset(dp,0x7f,sizeof(dp));//字节赋值
dp[0][0]=a[0];
}
void win()
{
for(int i=1; i<n; ++i) //枚举塔
for(int j=0; j<i; ++j) //枚举前点
{
if(dp[i-1][j] == inf) continue;
if(a[i] < dp[i-1][j])
{
dp[i][j+1]=min(dp[i-1][j]+a[i],dp[i][j+1]);//先直接加到前面，后面再决策他是否最优
int k=0,rp=a[i];//向后找
while(rp<dp[i-1][j])
rp+=a[(++k) + i];
if(rp<dp[i-1][j])//后面所以的值都加起来都没前面的高，这个情况应舍弃
continue;
dp[i+k][j+k]=min(rp,dp[i+k][j+k]);
}
else dp[i][j]=a[i];
}
for(int i=0; i<=5000; ++i)
if(dp[n-1][i]<inf)
{
printf("%d\n",i);
break;
}
}
};
int main()
{
int n;
while(scanf("%d",&n)==1)
{
Solution OMG(n);
OMG.win();//OMG必胜，S5冠军，加油！
}
return 0;
}


• 本文已收录于以下专栏：

举报原因： 您举报文章：codeforces 229/D 动态规划 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)