问题 A: sciorz画画

时间限制: 1 Sec  内存限制: 128 MB
提交: 845  解决: 159
[状态] [提交] [命题人:外部导入]

题目描述

众所周知,sciorz会画画。某天,sciorz画了一个凸多边形,这个多边形的每个顶点都有一个权值a[i]。sciorz觉得这个凸多边形不够美丽,于是他决定在n个点之间连线,最终用n-3条不相交的线将这个凸n边形分割成n-2个三角形。sciorz认为,一个三角形的美丽值是三个顶点权值的乘积,凸多边形的美丽值是其内部三角形的美丽值的和。sciorz想找到一种分割方案,使得这个凸多边形的美丽值最大。sciorz忙着刷难题,所以他随手就把这个签到题扔给你,希望你帮sciorz算出最大的美丽值。

输入

第一行一个t,表示有t组样例。
每组样例的第一行是一个n,表示多边形的边数。
第二行n个数,第i个数表示多边形第i个顶点的权值a[i],按逆时针顺序给出。

输出

对于每组样例,输出一行。格式为"Case #x: y",x为样例编号,y为答案。

样例输入 Copy

2
3
1 2 3 
4
1 2 3 4

样例输出 Copy

Case #1: 6
Case #2: 32

提示

第一个样例只有一个三角形,所以不用分割,答案是1*2*3=6。
第二个三角形,最优分割方案是分割为1 2 4和2 3 4两个三角形,答案是1*2*4+2*3*4=32

1<=t<=100
3<=n<=100
1<=a[i]<=100

 

参考:

https://www.cnblogs.com/Jason-Damon/p/3298172.html

https://www.cnblogs.com/wkfvawl/p/11631227.html

 

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 120;

int a[N];
int dp[N][N];   ///最优权值
int s[N][N];    ///s[i][j]为点i和点j组成三角形的第三个点

int weight(int i, int j, int k) ///权函数值
{
    return a[i] * a[j] * a[k];
}

int main()
{
    int n, t, kcase = 0;
    scanf("%d", &t);
    while(t--)
    {
        memset(dp, 0, sizeof(dp));
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i)
        {
            scanf("%d", &a[i]);
        }
        for(int r = 2; r <= n; ++r)  ///枚举两点间距
        {
            for(int i = 1; i <= n - r + 1; ++i)  ///第一个点
            {
                int j = i + r - 1;      ///第二个点
                int maxx = 0;           ///以i, j为顶点组成三角形的最大权值
                for(int k = i; k < j; ++k)  ///枚举第三个点与i, j组成三角形
                {
                    dp[i][j] = dp[i][k] + dp[k + 1][j] + weight(i - 1, k, j);
                    if(dp[i][j] > maxx)
                    {
                        maxx = dp[i][j];
                        s[i][j] = k;
                    }
                }
                dp[i][j] = maxx;
            }
        }
        cout<<"Case #"<<++kcase<<": "<<dp[1][n]<<'\n';
    }
    return 0;
}