P1063 能量项链 【区间dp】

P1063 能量项链

 

 

输入输出样例

输入 #1
4
2 3 5 10
输出 #1
710

说明/提示

NOIP 2006 提高组 第一题

 

思路

  很像石子合并的一道题,只不过把获得的价值给改了一下。

  如果有两堆石子可以合并,分别为 ( i , k ) , ( k + 1, j ) ,获得的价值为 head [ i ] * tail [ k ] * tail [ j ]。

  然后像石子合并那样做就可以了。

 

CODE

 

#include <bits/stdc++.h>
#define dbg(x) cout << #x << "=" << x << endl
#define eps 1e-8
#define pi acos(-1.0)

using namespace std;
typedef long long LL;

const int inf = 0x3f3f3f3f;

template<class T>inline void read(&res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}

namespace _buff {
    const size_t BUFF = 1 << 19;
    char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
    char getc() {
        if (ib == ie) {
            ib = ibuf;
            ie = ibuf + fread(ibuf, 1, BUFF, stdin);
        }
        return ib == ie ? -1 : *ib++;
    }
}

int qread() {
    using namespace _buff;
    int ret = 0;
    bool pos = true;
    char c = getc();
    for (; (< '0' || c > '9') && c != '-'; c = getc()) {
        assert(~c);
    }
    if (== '-') {
        pos = false;
        c = getc();
    }
    for (; c >= '0' && c <= '9'; c = getc()) {
        ret = (ret << 3) + (ret << 1) + (^ 48);
    }
    return pos ? ret : -ret;
}

const int maxn = 307;

int n;

int head[maxn];
int tail[maxn];
int f[maxn][maxn];

int main()
{
    read(n);
    for ( int i = 1; i <= n; ++) {
        read(head[i]);
        head[+ i] = head[i];
    }
    for ( int i = 1; i <= 2 * n - 1; ++) {
        tail[i] = head[+ 1];
    }
    int ans = -1;
    tail[2 * n] = head[1];
    for ( int z = 1; z <= n - 1; ++) {//!枚举区间长度
        for ( int i = 1; i <= 2 * n - z; ++) {
            int j = i + z;
            for ( int k = i; k <= j - 1; ++) {
                f[i][j] = max(f[i][j], f[i][k] + f[+ 1][j] + head[i] * tail[k] * tail[j]);
                ans = max(ans, f[i][j]);
            }
        }
    }
    cout << ans << endl;
    return 0;
}
posted @ 2020-03-21 17:56  Orangeko  阅读(298)  评论(0编辑  收藏  举报