zoukankan      html  css  js  c++  java
  • 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
    ", ans);
        return 0;
    }
  • 相关阅读:
    常见的五种App开发模式
    iOS提供的实用的属性和方法
    iOS开发思想
    iOS函数式编程
    iOS链式编程范例
    ios不起眼的错误
    iOS将汉字转成拼音
    ReactiveCocoa
    LuaViewSDK
    pycharm配置qtdesigner
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9433880.html
Copyright © 2011-2022 走看看