区间DP(POJ1651)

Description

 

有一个长度为n的序列,现取出其中除了最左和最右的元素(顺序任意),取出一个元素的代价为它本身乘相邻元素的乘积,现在想要以最小的代价取出这些元素。

Input

 

第一行输入一个n,代表元素的数量(n <= 100)第二行输入n个数 (a[i] <= 100);

Output

 

输出最小代价

Sample Input 1 

6
10 1 50 50 20 5

Sample Output 1

3650

 

题解:

首先第一层循环枚举长度,dp[i][j]表示把i,j取出需要的最小代价,然后枚举最后i,j之间最后取的数。

#include <bits/stdc++.h>

using namespace std;

const long long INF = 1LL << 59;
int main()
{
    ios::sync_with_stdio(false), cin.tie(0);
    int n;
    while(cin >> n) {
        vector<long long> a (n + 2);
        vector< vector<long long> > dp (n + 1, vector<long long> (n + 1, INF));
        for(int i = 1; i <= n; ++i) cin >> a[i];
        for(int i = 1; i <= n; ++i) {
            if(i == 1 || i == n) dp[i][i] = dp[i][i] = 0;
            else dp[i][i] = a[i - 1] * a[i + 1] * a[i];
        }
        for(int i = 1; i <= n; i ++) {
            for(int j = i - 1; j >= 1; -- j) {
                dp[i][j] = 0;
            }
        }
        for(int d = 2; d < n; ++d) {
            for(int st = 2; st + d - 1 < n; ++st) {
                int ed = st + d - 1;
                for(int k = st; k <= ed; ++k) {
                    dp[st][ed] = min(dp[st][ed],  dp[st][k - 1] + dp[k + 1][ed] + a[k] * a[st - 1] * a[ed + 1]);
                }
            }
        }
        cout << dp[2][n-1] << '\n';
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值