动态规划——靶场上有n块靶排成一排

靶场上有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]

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值