[区间DP] POJ 3186

双端队列最大和DP算法
本文介绍了一个关于双端队列的问题:如何通过动态规划算法计算从队列中取出元素并按特定规则计算得到的最大总和。该文详细阐述了算法的实现过程,并附带完整的代码示例。

题意

n个数在一个双端队列中,每次从队首或队尾出。出的第n个数乘以n,最后加起来,求最大和。

思路

第一次区间dp
dp[i][j] 代表从i取到j的最大总数
dp[i][j] = max(dp[i+1][j]+a[i](n+i-j) , dp[i][j-1]+a[j](n+i-j));

代码

#include <algorithm>
#include <cstdio>
#include <iostream>

#define N 2200
#define INF 0x7f7f7f7f

using namespace std;

int val[ N ];
int dp[ N ][ N ];

int main () {
    int n;
    while ( ~scanf ( "%d", &n ) ) {
        for ( int i = 0; i < n; ++i ) {
            scanf ( "%d", &val[ i ] );
            //从最后一个 ( 第n天 )往前取,直到取完所有
            // dp[ i ][ i ] = val[ i ] * n;
        }

        //从区间长度为1开始一直到n
        for ( int len = 0; len < n; ++len )
            //从i开始
            for ( int i = 0; i + len < n; ++i ) {
                int l = i, r = i + len;
                dp[ l ][ r ] = max ( dp[ l + 1 ][ r ] + val[ l ] * ( n + l - r ),
                                     dp[ l ][ r - 1 ] + val[ r ] * ( n + l - r ) );
            }
        printf ( "%d\n", dp[ 0 ][ n - 1 ] );
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值