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(T &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 (; (c < '0' || c > '9') && c != '-'; c = getc()) {
assert(~c);
}
if (c == '-') {
pos = false;
c = getc();
}
for (; c >= '0' && c <= '9'; c = getc()) {
ret = (ret << 3) + (ret << 1) + (c ^ 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; ++i ) {
read(head[i]);
head[n + i] = head[i];
}
for ( int i = 1; i <= 2 * n - 1; ++i ) {
tail[i] = head[i + 1];
}
int ans = -1;
tail[2 * n] = head[1];
for ( int z = 1; z <= n - 1; ++z ) {//!枚举区间长度
for ( int i = 1; i <= 2 * n - z; ++i ) {
int j = i + z;
for ( int k = i; k <= j - 1; ++k ) {
f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + head[i] * tail[k] * tail[j]);
ans = max(ans, f[i][j]);
}
}
}
cout << ans << endl;
return 0;
}