luogu1063 能量项链

题目大意

  有一串项链,项链上的每个珠子有首尾两个数字,首尾相连的两个珠子的尾数字和头数字相同。每次选择相连的一对珠子,得到第一个项链的首数字*第一个项链的尾数字(第二个项链的首数字)*第二个项链的尾数字的能量,并将两个珠子合并,首数字为原来第一个项链的首数字,尾数字为第二个项链的尾数字,直到只剩一个珠子为止。问每次得到的能量之和的最大值。

错误思路

  本题可以换一个说法:输入数据中的数字组成一个环,每次选连续三个数字,结果加上三个数字乘积,再将中间数字去除。

  我们发现这道题跟“合并果子”有些像。于是我们有一个贪心思路:每次选择环中最小的数字,将该数字和左右两侧的两个数字作为当前选择的三个数字,然后将该数字从环中删除。这样做的理由是这会使数值更大的数字被乘的次数更多,贡献更大。但是这种做法错在不能保证很大的数字乘足够多次。

  那么我们可以想想动规,但这种选三去一的选择方式使我们无法写出递归式。

正解

  以项链为单位进行区间DP(拆开二倍)即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAX_N = 210;
int HeadVal[MAX_N], F[MAX_N][MAX_N];

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &HeadVal[i]);
        HeadVal[i + n] = HeadVal[i];
    }
    HeadVal[n * 2 + 1] = HeadVal[1];
    for (int len = 2; len <= n; len++)
        for (int i = 1; i <= n * 2 - len + 1; i++)
            for (int lLen = 1; lLen <= len - 1; lLen++)
                F[i][i + len - 1] = max(F[i][i + len - 1], F[i][i + lLen - 1] + F[i + lLen][i + len - 1] + HeadVal[i] * HeadVal[i + lLen] * HeadVal[i + len]);
    int ans = 0;
    for (int i = 1; i <= n; i++)
        ans = max(ans, F[i][i + n - 1]);
    printf("%d\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/headboy2002/p/9433880.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值