列表

详情


DP48. 能量项链

描述

在Mars星球上,每个Mars人都随身佩带着一串能量项链。在项链上有N颗能量珠。能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数。并且,对于相邻的两颗珠子,前一颗珠子的尾标记一定等于后一颗珠子的头标记。因为只有这样,通过吸盘(吸盘是Mars人吸收能量的一种器官)的作用,这两颗珠子才能聚合成一颗珠子,同时释放出可以被吸盘吸收的能量。如果前一颗能量珠的头标记为m,尾标记为r,后一颗能量珠的头标记为 r,尾标记为 n,则聚合后释放的能量为 (Mars单位),新产生的珠子的头标记为 m,尾标记为 n。
需要时,Mars人就用吸盘夹住相邻的两颗珠子,通过聚合得到能量,直到项链上只剩下一颗珠子为止。显然,不同的聚合顺序得到的总能量是不同的,请你设计一个聚合顺序,使一串项链释放出的总能量最大。

例如:设N=4,4颗珠子的头标记与尾标记依次为(2,3) (3,5) (5,10) (10,2)。我们用记号⊕表示两颗珠子的聚合操作,(j⊕k)表示第j,k两颗珠子聚合后所释放的能量。则第4、1两颗珠子聚合后释放的能量为:(4⊕1)=10*2*3=60。
这一串项链可以得到最优值的一个聚合顺序所释放的总能量为
((4⊕1)⊕2)⊕3)=10*2*3+10*3*5+10*5*10=710。
第四颗珠子先和第一颗珠子聚合得到一个 (10,3) 的珠子,然后与第二颗珠子聚合得到 (10,5) ,然后与第三颗珠子聚合得到 (10,10)

数据范围: ,珠子上的值都满足 ,由于聚合的能量可能会非常大,所以请你对 取模

输入描述

第一行输入一个正整数 n ,表示珠子的个数。
第二行输入 n 个正整数,表示项链上的珠子的头标记的值,其中 i < n 的珠子的尾标记的值都是第 i+1 颗珠子的头标记的值,第 n 颗珠子的尾标记的值是第 1 颗头标记的值。    

输出描述

输出能得到的最优值

示例1

输入:

4
2  3  5  10

输出:

710

说明:

如题面解释

原站题解

C++ 解法, 执行用时: 4ms, 内存消耗: 540KB, 提交时间: 2022-04-05

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
const int N=2*105;
int n;
int a[N],dp[N][N];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int len=1;len<n;len++){
        for(int i=0;i<2*n-len;i++){
            int j=i+len;
            for(int k=i;k<j;k++){
                dp[i][j]=max(dp[i][j],
               (dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1])%mod);
            }
        }
    }
    int res=0;
    for(int i=0;i<n;i++)    res=max(res,dp[i][i+n-1]);
    cout<<res<<endl;
     //for(int i=0;i<n;i++)    cout<<dp[i][i+n-1]<<" ";
    return 0;
}

C 解法, 执行用时: 5ms, 内存消耗: 432KB, 提交时间: 2022-06-22

int max(int a, int b) {
    return a > b ? a : b;
}

int main() {
    int n;
    scanf("%d", &n);
    
    int start[2 * n + 1];
    for (int i = 0; i < n; i++) {
        scanf("%d", &start[i]);
        start[i+n] = start[i];
    }
    start[2 * n] = start[0];
    
    int **dp = (int **)malloc(sizeof(int *) * 2 * n);
    for (int i = 0; i < 2 * n; i++) {
        dp[i] = (int *)malloc(sizeof(int) * n);

        memset(dp[i], 0, sizeof(int) * n);
    }
    
    int maxPower = 0;
    for (int d = 1; d < n; d++) {
        for (int i = 0; i < 2 * n - d; i++) {
            for (int k = 0; k < d; k++) {
                dp[i][d] = max(dp[i][d], 
                               (dp[i][k] + dp[i+k+1][d-k-1] + start[i] * start[i+k+1] * start[i+d+1]) % 1000000007);
            }
        }
    }
    for (int i = 0; i < n; i++) {
        maxPower = max(maxPower, dp[i][n-1]);
    }
    
    printf("%d", maxPower);
    
    for (int i = 0; i < 2 * n; i++) {
        free(dp[i]);
    }
    free(dp);
    
    return 0;
}

C++ 解法, 执行用时: 5ms, 内存消耗: 548KB, 提交时间: 2022-08-06

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
const int N=2*105;
int n;
int a[N],dp[N][N];
int main(){
	cin>>n;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		a[i+n]=a[i];
	}
	for(int len=1;len<n;len++)
	{
		for(int i=0;i<2*n-len;i++)
		{
			int j=i+len;
			for(int k=i;k<j;k++)
			{
				dp[i][j]=max(dp[i][j],(dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1])%mod);
			}
		}
	}
	int res=0;
	for(int i=0;i<n;i++)
	res=max(res,dp[i][i+n-1]);
	cout<<res<<endl;
	return 0;
}

C++ 解法, 执行用时: 5ms, 内存消耗: 552KB, 提交时间: 2022-08-06

#include <bits/stdc++.h>
using namespace std;
//typedef long long LL;
const int mod=1e9+7;
const int N=2*105;
int n;
int a[N],dp[N][N];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int len=1;len<n;len++){
        for(int i=0;i<2*n-len;i++){
            int j=i+len;
            for(int k=i;k<j;k++){
                dp[i][j]=max(dp[i][j],
               (dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1])%mod);
            }
        }
    }
    int res=0;
    for(int i=0;i<n;i++)    res=max(res,dp[i][i+n-1]);
    cout<<res<<endl;
     //for(int i=0;i<n;i++)    cout<<dp[i][i+n-1]<<" ";
    return 0;
}
// #include <iostream>
// using namespace std;

// const int N=210;
// int w[N],dp[N][N],mod=1e9+7;

// int main(){
//     int n;
//     cin>>n;
//     for(int i=0;i<n;i++){
//         cin>>w[i];
//         w[i+n]=w[i];//构成环型
//     }
//     for(int len=3;len<=n+1;len++){
//         for(int l=1;l<=2*n+1-len;l++){
//             int r=l+len-1;
//             for(int k=l+1;k<r;k++){
//                 dp[l][r]=max(dp[l][r]%mod,(dp[l][k]+dp[k][r]+w[l]*w[k]*w[r])%mod);
//             }
//         }
//     }
//     int res=0;
//     for(int i=1;i<=n;i++) res=max(res,dp[i][i+n]);
//     cout<<res;
    
//     return 0;
// }

C++ 解法, 执行用时: 5ms, 内存消耗: 552KB, 提交时间: 2022-05-15

#include <bits/stdc++.h>
using namespace std;
//typedef long long LL;
const int mod=1e9+7;
const int N=2*105;
int n;
int a[N],dp[N][N];
int main(){
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
        a[i+n]=a[i];
    }
    for(int len=1;len<n;len++){
        for(int i=0;i<2*n-len;i++){
            int j=i+len;
            for(int k=i;k<j;k++){
                dp[i][j]=max(dp[i][j],
               (dp[i][k]+dp[k+1][j]+a[i]*a[k+1]*a[j+1])%mod);
            }
        }
    }
    int res=0;
    for(int i=0;i<n;i++)    res=max(res,dp[i][i+n-1]);
    cout<<res<<endl;
     //for(int i=0;i<n;i++)    cout<<dp[i][i+n-1]<<" ";
    return 0;
}

上一题