前言
今天中午笔者立下了一个flag帖,晚自习的笔者来解决flag了!~
参考题解
题目描述
有 n 个西瓜,编号为0 到 n-1,每个西瓜上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的西瓜。每当你戳破一个西瓜 i 时,你可以获得 nums[left] *nums[i] *nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个西瓜的序号。注意当你戳破了西瓜 i 后,西瓜 left 和西瓜 right 就变成了相邻的西瓜。
求所能获得硬币的最大数量。
输入格式
共两行。
第一行:一个正整数n,代表西瓜个数。
第二行:共n个数字,每个数字表示西瓜上标的数字。
输出格式
一行,一个整数,获得硬币的最大数量。
样例
样例输入
4
3 1 5 8
样例输出
167
解释:
nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 315 + 358 + 138 + 181 = 167
数据范围与提示
你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的西瓜,所以并不能被戳破。
0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
思路
设dp[i][j]为i~j之间最大的和,(i, j)
因为这与前一和后一都有关
枚举k点(k为最后戳爆的点)那么i,j就可以相邻
如下图
那么我们就需要知道dp[i][k], 和dp[k][j](再次重申开区间)
代码
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 505;
int n;
int a[maxn];
long long dp[maxn][maxn];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++){
scanf("%d", &a[i]);
}
a[0] = 1;
a[n + 1] = 1;
for(int i = n; i >= 0; i --){
for(int j = i + 2; j <= n + 1; j ++){
for(int k = i + 1; k < j; k ++){
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + a[i] * a[j] * a[k]);
}
}
}
printf("%d", dp[0][n + 1]);
return 0;
}
如果觉得有帮助的话,记得留下你的赞哦~