zoukankan      html  css  js  c++  java
  • 铁塔 题解

    题目描述

    Rainbow 和 Freda 要在 Poetic Island 市的一座山脚下盖房子定居了……盖房子需要钢材,幸运的是,这里有排成一行的 n 座废弃的铁塔,从左到右编号为1~n,其中第 i 座的高度为 h[i]。Rainbow 和 Freda 想盖一座上面小下面大的城堡,并且城堡的层数尽可能多。因此,他们要把这些铁塔分成尽量多组,每组内的铁塔编号必须是连续的,并且从左到右各组内铁塔的高度之和单调不减。最后,他们会用每组铁塔所提供的钢材构成一层城堡。 但是 Rainbow 和 Freda 简直弱爆了有木有,于是请你帮忙计算一下最多能分成多少组呢?

    输入输出格式

    输入格式:

    第一行一个整数 n。 第二行 n 个整数,第 i 个整数表示 h[i]。

    输出格式:

    输出一个整数,表示(n - 最多能分成的组数)。

    题解

      考试的时候一看就觉得是到贪心,十几分钟就码完了,后来完了,想了想发现自己凉了。如果我们贪心的话,贪心策略就应该是尽可能的少拿前面的。举组反例吧,对于2 2 1 3 3,对于贪心就会这样选择(2) (2) (1 3) 3最后输出3,而最优解却应该是(2) (2 1) (3) (3)最后答案是4。

      所以我们就只能考虑用动态规划了。

      状态:f[i]表示前 i 个铁塔最多组成多少组。

         last[i]前 i 个铁塔的最优解下,最后一组铁塔的数量。

      转移 :我们求一个前缀和sum[i]表示前i 个铁塔的高度和,我们可以利用贪心的思想得到当f[i]尽量大时,last[i]会越来越小

         

    代码

     #include <bits/stdc++.h>
     using namespace std;
     const int MAX = 5005;
     long long f[MAX], sum[MAX], last[MAX], a[MAX];
     int main()
     {
         //freopen("tower.in", "r", stdin);
         //freopen("tower.out", "w", stdout);
         int n;
         scanf("%d", &n);
         for(int i = 1; i <= n; ++ i)
         {
             scanf("%lld", &a[i]);
             sum[i] = sum[i - 1] + a[i];
         }
         f[0] = 0;
         for(int i = 1; i <=n; ++ i)
             for(int j = 0; j < i; ++ j)
                 if(sum[i] - sum[j] >= last[j])
                 {
                     f[i] = f[j] + 1;
                     last[i] = sum[i] - sum[j];
                 }
         printf("%lld
    ", n - f[n]);
     }
  • 相关阅读:
    开源mvcpager分页控件分页实例
    「YNOI2016」自己的发明
    「SNOI2017」一个简单的询问
    势能分析(splay分析)
    「Ynoi2018」未来日记
    「JOISC 2016 Day 1」棋盘游戏
    「ZJOI2014」璀灿光华
    「ZJOI2019」线段树
    「科技」区间众数
    「ZJOI2017」树状数组
  • 原文地址:https://www.cnblogs.com/2020pengxiyue/p/9338643.html
Copyright © 2011-2022 走看看