• HDU 1024 A


    http://acm.hdu.edu.cn/showproblem.php?pid=1024

    刚开始的时候没看懂题目,以为一定要把那n个数字分成m对,然后求m对中和值最大的那对

    但是不是,题目说的只是选出m对,所以有些数字是可以不用的。

    那么就用

    dp[i][j]表示前j个数,分成了i段,其中第a[j]个数必定包含在第i段之中的最大和值。就是a[j]必定选了而且在第i段之中。

    至于为什么要这样设。

    1、如果想得到ans,只需要扫描一次ans = max(ans, dp[m][m....n]),因为第m段肯定是以a[]中某个数字结尾。同时至少要有m个数才能分成m段

    2、更多的是看做题量,很多dp都是这样设,(最大字段和等)。所以dp靠得还是经验,我还是去多多刷题补上我的弱项----dp

    转移:

    对于每个a[j],要么,a[j]独立一组(独立在第i组上),所以此时的贡献是max(dp[i - 1][k]) + a[j],其中 i - 1 <= k <= j - 1

    k为什么要大于等于i - 1呢,因为起码要有i - 1个数才能组成i - 1组。然后选取最大的来和a[j]组合成i个组。

    要么, a[j]在第i组上但是a[j - 1]也在第i组上(这样是用来判断和前面的连接成一个组的) 贡献:dp[i][j - 1] + a[j]

    直接转移m * n * n

    考虑到第一个转移的时候,肯定是从dp[i - 1][k]中选一个最大的来和a[j]相加,所以考虑到用个preMx[j]表示前j个数在分成i - 1个组时候的最大值。能压缩成n * m

    因为dp只和上一维有关,故可以用滚动数组压缩空间、

    滚动数组就是,

    例如现在要算分成i个组的,那么你分成i - 2个组的已经没用了,故可以舍弃

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    const int maxn =  1000000 + 20;
    LL dp[maxn];
    LL preMx[2][maxn];
    int a[maxn];
    int n, m;
    void work() {
        for (int i = 0; i <= n; ++i) {
            preMx[0][i] = 0;
            preMx[1][i] = 0;
            dp[i] = 0;
        }
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        int now = 0;
        LL mx;
        for (int i = 1; i <= m; ++i) {
            mx = -inf;
            for (int j = i; j <= n; ++j) { //因为分成i组,起码要有i个数
                dp[j] = max(preMx[!now][j - 1] + a[j], dp[j - 1] + a[j]);
                mx = max(mx, dp[j]);
                preMx[now][j] = mx;
            }
            now = !now;
        }
        printf("%I64d
    ", mx);
    }
    int main() {
    #ifdef local
        freopen("data.txt","r",stdin);
    #endif
        while (scanf("%d%d", &m, &n) != EOF) work();
        return 0;
    }
    View Code
  • 相关阅读:
    [ Linux ] rsync 对异地服务器进行简单同步
    [ Skill ] 遍历整个项目设计的两个思路
    [ Skill ] 不常用的函数笔记
    [ Perl ] Getopt 使用模板
    [ Skill ] 两个 listBox 数据交换的模板
    [ Linux ] "真"后台 nohup
    [ VM ] VirtualBox 压缩 .vdi
    [ Skill ] Layout 工艺移植,还原库调用关系
    win8 hyper-v 禁用不必卸载虚拟机
    BM算法解析(计算机算法-设计与分析导论(第三版))
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/5994439.html
Copyright © 2020-2023  润新知