P1063 能量项链 【区间dp】
作者:互联网
P1063 能量项链
输入输出样例
输入 #14 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; }
标签:head,int,ans,++,tail,maxn,项链,P1063,dp 来源: https://www.cnblogs.com/orangeko/p/12540636.html