靶场上有n块靶排成一排,从左到右依次编号为1、2、3、...n,且每块靶上都标有一个整数。
当某块靶被击中后,击中者会得到x*y*z 的积分。(y表示被击中的靶上的数,x表示其左侧最近且未被击中的靶上的数,z表示其右侧最近且未被击中的靶上的数。如果其左侧不存在未被击中的靶,则x为1;如果其右侧不存在未被击中的靶,则z为1。)
计算完积分后,这块靶就会退出靶场(不在这排靶中)。
请计算击中所有靶后能得到的最高积分是多少?
例如:n=4,表示有4块靶,这4块靶上的数从左到右分别是3、2、4、6;
按照下列顺序打靶,可以得到最高积分:
1.打2号靶,得到的积分是24(3*2*4);
2.打3号靶,得到的积分是72(3*4*6);
3.打1号靶,得到的积分是18(1*3*6);
4.打4号靶,得到的积分是6(1*6*1);
最终获得的积分是120(24+72+18+6)。
输入描述
第一行输入一个整数n(1≤n≤300),表示靶场上靶的数量
第二行输入n个整数(1≤整数≤100),分别表示从左到右每块靶上的数,整数之间以一个空格隔开。
输出描述
输出一个整数,表示击中所有靶后能得到的最高积分
样例输入
4
3 2 4 6
样例输出
120
思路:
每次射击后靶的退出会影响左右靶的选择,可以采用区间动态规划
动态规划的核心思想是最终的状态可以由前面的状态加上当前的状态
在这里最终是只剩下一个靶子,所以假设区间i,j中最后被集中的靶子为k
则转移方程:dp[i][j]=max (a[k]*a[i-1]*a[j+1] + dp[i][k-1] + dp[k+][j] ) k=i到j
其中dp[i][j]表示击中i j 之间所有靶子的最佳得分 a[i]表示每块靶上的数
也就是说dp[i][j] 击完i到j之间所有靶子的最佳的分应该是 击中k的得分 + k左边的最佳得分 +k右边的最佳得分
初始化:
a[0] a[n+1] =0 因为如果其左侧不存在未被击中的靶,则x为1;如果其右侧不存在未被击中的靶,则z为1。
a[1]-a[n] 为输入
dp[i][j] 当i==j时 击中的靶子一定为k=i=j 此时得分为 a[k]*a[k-1]*a[k+1]
计算顺序:
i==j只有一块靶已经初始化了 接着从由两块靶一直到有n块靶对比最后击中的是哪个k时dp得分最大
for(int len=2;len<=n;len++){
for(int i=1;i+len-1<=n;i++){
for(int k=i;k<=i+len-1;k++){
int score=a[k]*a[i-1]*a[j+1] + dp[i][k-1] + dp[k+1][j];
dp[i][i+len-1]=max(dp[i][i+len-1],score);
}
}
}
输出dp[1][n]