题目链接 http://www.rqnoj.cn/Problem_5.html
此题给出的是一条项链存在首尾相连的情况,可以用链表实现,但是项链可以以里边的任何两个相邻的数据作为头和尾,这样链表会不方便。如何用常用的数据结构来存储数据呢?什么线性结构可以做到数据首尾项链呢? 数组存储,然后循环时进行控制,但是循环时需要的判断十分复杂不可取。这时想到把数组开辟两倍的给出数据的空间,让后一半空间将前一半空间存储的数据进行复制即可完成要求。
题目中出现的基本状态如何存储呢? 要求最大值,整体不易解决分成小问题,就先求一小段项链的最大值,而这一小段项链只需记录从哪一颗开始哪一颗结束,开辟一二维数据进行存储,f[i][j]。
状态转移就根据题目给出的例子很容易看出, f[i][j] = f[i][k] + f[k+1][j] + a[i]*a[k+1]*a[j+1],从相邻的开始考虑逐渐扩展。
#include <stdio.h>
#include <string.h>
#define MAX 205
int N, max;
int a[MAX], f[MAX][MAX];
int main()
{
scanf("%d", &N);
memset(f, 0, sizeof(f));
for(int i = 1; i <= N; i++)
{
scanf("%d", &a[i]);
a[i + N] = a[i];
}
max = 0;
for(int j = 2; j <= 2 * N - 1; j++)
{
for(int i = j - 1; i >= 1 && j - i < N; i--)
{
for(int k = i; k <= j - 1; k++)
{
if(f[i][j] < f[i][k] + f[k + 1][j] + a[i] * a[k + 1] * a[j + 1])
{
f[i][j] = f[i][k] + f[k + 1][j] + a[i] * a[k + 1] * a[j + 1];
}
}
}
}
for(int i = 1; i <= N; i++)
{
if(max < f[i][i + N - 1]) max = f[i][i + N - 1];
}
printf("%d\n", max);
return 0;
}