codeforces 229/D 动态规划

题目链接: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
5
8 2 7 3 1
output
3
input
3
5 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值