【cf229D】Towers

来源:互联网 发布:显示淘宝下架插件 编辑:程序博客网 时间:2024/06/05 02:19
  • link to problem

  • 【题目大意】

有n(1<=n<=5,000)座塔排在一条直线上,从左到右每个塔的高度分别为hi(1<=hi<=100,000),每次操作你可以选择一座塔(假设是第i座),用吊车把它吊起来,然后放到与它相邻的一座塔上(可以是第i-1座也可以是第i+1座),这样,新塔的高度为两座塔的和,完成操作后,塔的总数减少一座。问最少需要多少次操作可以使得所有的塔从左到右形成一个非递减序列。


  • 【题解】贪心+dp

    首先我们可以知道,当 j < i 时必有a[j] <= a[i];
    设 s[i]=∑a[j] (1<=j<=i) , 所以如果要合并第 i-j 座塔,必然满足:s[j]-s[i-1]>=a[i-1],此时可以根据贪心思想更新a[i-1];


  • 【呆马(⊙o⊙)】
#include <cstdio>#include <iostream>#define inf 1000000000long long n,a[5010],f[5010],s[5010];int main(){    scanf("%I64d\n",&n);    for (int i=1;i<=n;++i) scanf("%I64d ",&a[i]);    for (int i=1;i<=n;++i) s[i]=a[i]+s[i-1];    for (int i=1;i<=n;++i) a[i]=f[i]=inf;    for (int i=1;i<=n;++i)         for (int j=0;j<i;++j)            if (a[j]<=s[i]-s[j])             {                f[i]=std::min(f[i],f[j]+i-j-1);                if (a[i]>s[i]-s[j]) a[i]=s[i]-s[j];            }    printf("%I64d\n",f[n]);    return 0;}
0 0