dotcpp 蓝桥杯往年题目 能量项链

题目描述
在这里插入图片描述
简言之,就是一串编号为从1到n的首尾相连的环状珠子,每一个珠子有头部标记和尾部标记,第i个珠子的尾部标记是第i+1个珠子的首部标记,第i个珠子的首部标记是第i-1个珠子的尾部标记,可以理解为一个循环链表。

原题链接
链接: 原题

解题思路及代码
思路一:贪心做法
每次找到头部标记最小的珠子作为两个珠子合并时的后一个珠子,这样的话每次合并可以消去一个最小的值,该最小值对后面合并时乘积的影响达到最小,即局部最优解构成整体最优解,符合贪心的思想

#贪心
n=int(input())
lst=list(map(int,input().split()))
sum=0
#需要处理n-1次合并
for i in range(n-1):
    pst=lst.index(min(lst))#每次找到最小的值作为要被消除的量,以避免它对后续的乘法造成影响
    sum+=lst[pst]*lst[pst-1]*lst[(pst+1)%(n-i)]
    lst.remove(lst[pst])
print(sum)

思路二:动态规划
使用动态规划需要考虑三个内容,状态表示、初始状态、转移方程
首先为了解决模拟出循环链表的问题,将输入的列表再copy两份放尾部append一下即可,这是为了保证当需要某一个珠子的尾部标记时需要索引加一,多开几份可以避免index out of range
然后根据之前的经验,这道题和石子合并这道区间合并问题很类似,所以使用区间合并的方法

#状态表示:dp[i][j]表示第i颗珠子到第j颗珠子合成一个珠子所释放的最大能量
#初始状态:dp[i][j]=0
#状态转移:dp[i][j]=max{dp[i][k]+dp[k][j]+a[i]*a[k+1]*a[j+1]}
n=int(input())
lst=list(map(int,input().split()))
lst.extend(lst)
lst.extend(lst)#防止开小
dp=[[0]*n*3 for i in range(3*n)]
ans=0
for lenth in range(2,n+1):
    for i in range(2*n-lenth+1):
        j=i+lenth-1
        for k in range(i,j):
            dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]+lst[i]*lst[k+1]*lst[j+1])
for i in range(n):
    ans=max(ans,dp[i][i+n-1])
print(ans)
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

so.far_away

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值