zoukankan      html  css  js  c++  java
  • 洛谷P2300 合并神犇

    传送门啦

    分析:

    刚开始读完题后感觉很懵,怎么算都不是3,结果发现题目理解错了。题目要求的是求一个不降的序列,不是递减的(发现自己好傻)

    看明白题就好做了吧。经典的区间dp题,合并果子大家应该都做过,那个题求一个代价,这个题换成合并次数了,也差不多。

    本题要使一段序列合并成不下降序列,因为只能合并相邻的两个数,所以合并后的一个数必定是由原版序列中的一段进行数次合并得到的。考虑简单的贪心思路,对于第一个数,每次不停加入一个数直到它们的和大于第一个数停止,继续此操作,直到结束,但是这样显然是错误的,因为前面满足了条件不一定后面会最优(很简单思考懒的举例了)。

    由贪心思路引申到dp,因为是一段合并,考虑到前缀和sum[i],我们令f[i]表示到了第i个数为止所合并的次数,用一个辅助数组maxp[i]表示到了i为止合并后最大的一个数,于是得到状态转移方程:if(sum[i]-sum[j] >= maxp[j])f[i] = f[j] + j - i - 1(其中i > j)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn = 200005;
    
    inline int read(){
        char ch = getchar(); int f = 1 , x = 0;
        while(ch > '9' || ch < '0'){if(ch == '-') f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    
    int n,p[maxn];
    long long f[maxn],sum[maxn],maxp[maxn];
    
    int main(){
        n = read();
        for(int i=1;i<=n;i++) {
            p[i] = read();
            sum[i] = sum[i-1] + p[i];
        }
        int i,j;
        for(i=1;i<=n;i++){
            for(j=i-1;j>=0;j--)
                if(sum[i] - sum[j] >= maxp[j])
                    break;
            f[i] = f[j] + i - j - 1;
            maxp[i] = sum[i] - sum[j];
        }
        printf("%lld",f[n]);
        return 0;
    }
    顺风不浪,逆风不怂。
  • 相关阅读:
    jQuery的鼠标悬停时放大图片的效果
    判断一个字符串在另一个字符串中出现的次数
    .net中几个经常用到的字符串的截取
    云服务器 ECS CentOS 7 下重启 sshd 服务操作方法
    博客生涯开始咯
    Json 转 Map 的几种方式
    JS 折线图
    CSS样式优先级
    Arrays.asList 数组转集合 java.lang.UnsupportedOperationException错误
    Netty 笔记
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9864885.html
Copyright © 2011-2022 走看看