5194
https://www.luogu.com.cn/problem/P5194
P5194 [USACO05DEC] Scales S
题目描述
约翰有一架用来称牛的体重的天平。与之配套的是个已知质量的砝码(所有砝码质量的数值都在
位带符号整数范围内)。
每次称牛时,他都把某头奶牛安置在天平的某一边,然后往天平另一边加砝码,直到天平平衡,于是此时砝码的总质量就是牛的质量(约翰不能把砝码放到奶牛的那边,因为奶牛不喜欢称体重,每当约翰把砝码放到她的蹄子底下,她就会尝试把砝码踢到约翰脸上)。
天平能承受的物体的质量不是无限的,当天平某一边物体的质量大于时,天平就会被损坏。砝码按照它们质量的大小被排成一行。并且,这一行中从第
个砝码开始,每个砝码的质量至少等于前面两个砝码(也就是质量比它小的砝码中质量最大的两个)的质量的和。
约翰想知道,用他所拥有的这些砝码以及这架天平,能称出的质量最大是多少。由于天平的最大承重能力为 ,他不能把所有砝码都放到天平上。
现在约翰告诉你每个砝码的质量,以及天平能承受的最大质量,你的任务是选出一些砝码,使它们的质量和在不压坏天平的前提下是所有组合中最大的。
输入格式
第 行输入两个用空格隔开的正整数
。
第 到
行:每一行仅包含一个正整数,即某个砝码的质量。保证这些砝码的质量是一个不下降序列。
输出格式
输出一个正整数,表示用所给的砝码能称出的不压坏天平的最大质量。
输入输出样例 #1
输入 #1
3 15 1 10 20
输出 #1
11
代码:
import sys
input=sys.stdin.readline
fama=[0]
list1=[0]
n,c=map(int,input().split())
max_num=0
def dfs(cur,index):
global max_num,c
if cur+list1[index]<=max_num:
return
max_num=max(cur,max_num)
if index==0:
return
if cur+fama[index]<=c:
dfs(cur+fama[index],index-1)
dfs(cur,index-1)
i=1
while(i<=n):
m=int(input())
fama.append(m)
if fama[i]>c:
break
list1.append(list1[i-1]+fama[i])
i+=1
dfs(0,i-1)
print(max_num)
题解:
这道题是DFS和剪枝,通过学习别人的代码,总算明白了DFS和剪枝
这道题是斐波拉期数列,所以数据最多只有30. 最普通的算法应该是230 次运算
但可以通过剪枝去除无效的情况,上述剪枝有3个
if cur+list1[index]<=max_num:
return
1.list1为前缀和 当cur+list1[index]小于等于max_num,则不需要再往前遍历
if fama[i]>c:
break
2.当单个砝码大于c,则后续砝码都无效
if cur+fama[index]<=c:
dfs(cur+fama[index],index-1)
dfs(cur,index-1)
3.当 cur+fama[index]大于c,则跳过当前砝码
另外这行代码‘dfs(cur,index-1)’ 不仅处理了 ‘当 cur+fama[index]大于c,则跳过当前砝码 ’ 的情况
也处理了当 ‘dfs(cur+fama[index],index-1)’函数结束时的情况,相当于是处理完左子树,再处理右子树,而左子树是取fama[index],右子树是不取fama[index],而取fama[index-1],这样把每种情况都考虑到了,从而找到最优解。

查看13道真题和解析