记录蓝桥杯刷题,题目链接:P8709 [蓝桥杯 2020 省 A1] 超级胶水
题目
题目描述:
小明有 n 颗石子,按顺序摆成一排,他准备用胶水将这些石子粘在一起。
每颗石子有自己的重量,如果将两颗石子粘在一起,将合并成一颗新的石子,重量是这两颗石子的重量之和。
为了保证石子粘贴牢固,粘贴两颗石子所需要的胶水与两颗石子的重量乘积成正比,本题不考虑物理单位,认为所需要的胶水在数值上等于两颗石子重量的乘积。
每次合并,小明只能合并位置相邻的两颗石子,并将合并出的新石子放在原来的位置。
现在,小明想用最少的胶水将所有石子粘在一起,请帮助小明计算最少需要多少胶水。
输入格式:
输入的第一行包含一个整数 n,表示初始时的石子数量。
第二行包含 n 个整数w1,w2,⋯,wn 依次表示每颗石子的重量。
输出格式:
输出一行包含一个整数,表示最少需要的胶水数。
思考(错误)
以下思考内容为错误思路,不要看!
用w[i]表示i号石子重量。
最开始一看,觉得就是动态规划做题,设计两个量heavy与glue, heavy[i][j]表示从i号石子到j号石子总重量,glue[i][j]表示粘贴从i号石子到j号石子所需最少胶水量,那就可以有这样的公式:
然后,为了代码方便,可以换一个思路:
我首先找出来粘贴两个石子最少的胶水,然后三个、四个、五个,最后粘完全部石子,那么,首先可以得出:
假设粘贴k+1个石子,从i号石子到i+k号石子,最后粘贴的位置为j号石子与j+1号石子中间,那么有:
最后就可以通过循环完成了,代码如下:
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号石子,那么总胶水量为
同理,假设4个石子重量分别为a到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)就好了是吧······