codeforces 229/D 动态规划

来源:互联网 发布:windows系统文件损坏 编辑:程序博客网 时间:2024/05/29 06:49

题目链接:http://codeforces.com/problemset/problem/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
58 2 7 3 1
output
3
input
35 2 1
output
2

题意:

这个城市有n座塔,为了美观,需要后面的塔不能比前面的塔矮,所以需要你来整理,你的操作方式是可以把任意一个塔放到他相邻的一座塔上,组成一座新塔,

注意只能移到相邻的塔上,新塔还能继续移动,问你最少多少步可以完成

思路:

一开始我天真的以为是贪心,想在O(n)的复杂度上解决他,代码也写出来了,过了很多组数据,CF给后台,当我看那组我WA的数据的时候,我才意识到我的思路是完全错的,就扔掉了,过了好几个月才捡起来想了个DP的解法:

二维DP,dp[i][j]:i表示第i座塔移动的j步,他能达到的最矮的情况,dp不断更新,跑一遍O(n^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;}




1 0
原创粉丝点击