P8709 [蓝桥杯 2020 省 A1] 超级胶水(Python)

记录蓝桥杯刷题,题目链接:P8709 [蓝桥杯 2020 省 A1] 超级胶水

题目

题目描述:

小明有 n 颗石子,按顺序摆成一排,他准备用胶水将这些石子粘在一起。

每颗石子有自己的重量,如果将两颗石子粘在一起,将合并成一颗新的石子,重量是这两颗石子的重量之和。

为了保证石子粘贴牢固,粘贴两颗石子所需要的胶水与两颗石子的重量乘积成正比,本题不考虑物理单位,认为所需要的胶水在数值上等于两颗石子重量的乘积。

每次合并,小明只能合并位置相邻的两颗石子,并将合并出的新石子放在原来的位置。

现在,小明想用最少的胶水将所有石子粘在一起,请帮助小明计算最少需要多少胶水。

输入格式:

输入的第一行包含一个整数 n,表示初始时的石子数量。

第二行包含 n 个整数w1​,w2​,⋯,wn​ 依次表示每颗石子的重量。

输出格式:

输出一行包含一个整数,表示最少需要的胶水数。

思考(错误)

以下思考内容为错误思路,不要看!

用w[i]表示i号石子重量。

最开始一看,觉得就是动态规划做题,设计两个量heavy与glue, heavy[i][j]表示从i号石子到j号石子总重量,glue[i][j]表示粘贴从i号石子到j号石子所需最少胶水量,那就可以有这样的公式:

 

然后,为了代码方便,可以换一个思路:

我首先找出来粘贴两个石子最少的胶水,然后三个、四个、五个,最后粘完全部石子,那么,首先可以得出:

glue[i][j]=w[i]*w[j]\left ( j=i+1 \right )

假设粘贴k+1个石子,从i号石子到i+k号石子,最后粘贴的位置为j号石子与j+1号石子中间,那么有:

glue[i][i+k]=min(glue[i][j]+glue[j+1][i+k]+heavy[i][j]*heavy[j+1][i+k]),i<=j<i+k

最后就可以通过循环完成了,代码如下:

n=int(input())
w=input().split()
heavy=[]
glue=[]
for i in range(0,n):
    w[i]=int(w[i])
for i in range(0,n):
    next1=[]
    next2=[]
    for j in range(0,n):
        next1.append(0)
        next2.append(0)
    heavy.append(next1)
    glue.append(next2)    #初始化数组

for i in range(0,n):
    for j in range(i,n):
        for k in range(i,j+1):
            heavy[i][j]+=w[k]

for i in range(0,n-1):
    glue[i][i+1]=w[i]*w[i+1]

for k in range(2,n):
    for i in range(0,n-k):  #从glue[0][k]到glue[n-k-1][n-1]
        minx=9999999999
        for j in range(i,i+k):
            need=glue[i][j]+glue[j+1][i+k]+heavy[i][j]*heavy[j+1][i+k]
            if need<minx:
                minx=need
        glue[i][i+k]=minx

print(glue[0][n-1])

自信满满地提交,好,代码超时,内存过大

无可奈何

然后看了一下题解,破防了

正确题解

注意看,这个题目叫注意看()

注意看,假设三个石子重量分别为a,b,c,先粘1、2石子,再粘3号石子,那么总胶水量为

a*b+(a+b)*c=a*b+a*c+b*c

同理,假设4个石子重量分别为a到d,那么胶水总消耗:

a*b+a*c+a*d+b*c+b*d+c*d

显然可见,胶水消耗量跟粘贴顺序没关系,随便咋粘都可以······

那我那个动态规划算啥啊?!小丑竟是我自己

行吧,最后代码展示如下:

n=int(input())
w=input().split()
sum=0
for i in range(0,n):
    w[i]=int(w[i])
heavy=w[0]
for i in range(1,n):
    sum += heavy * w[i]
    heavy+=w[i]
print(sum)

好好好,时间复杂度只要O(n)就好了是吧······

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值