首页 > 试题广场 >

双袋购物

[编程题]双袋购物
  • 热度指数:1268 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解

一条马路上有 n 个点,从左到右从 1 到 n 编号。小明一开始在马路的最左边,一直往右走,一直走到马路的最右边,一直往右走,一直走到马路的最右边,中途不允许回头,只能往右走。

每个点上都有一个物品,第 i 个点的物品体积为 vi,价值为 wi,(注意:先输入体积再输入价值)小明有两个袋子,一号袋子和二号袋子,一号袋子体积为 A ,二号袋子体积为 B 。
最开始小明使用一号袋子,经过一个点的时候,他可以选择把点上的物品放入袋子中,但是袋中物品的总体积不能超过袋子的体积,也可以选择不拿这个物品。
在整个过程中的任意一个时刻,小明可以选择把一号袋子收起来,接下来使用二号袋子,一旦小明收起了一号袋子,之后他再也不能使用一号袋子,接下来的物品只能决策是否放入二号袋子中,且袋中的物品的总体积不能超过袋子容量。特别的,小明可以在最开始(遇到 1 号点之前)就换袋子,这样他全程都使用二号袋子 ;他也可以一直使用一号袋子,到最后也不收。
小明最后获得的价值为两袋子中物品价值和,问在最优策略下的最大价值。

数据范围:

输入描述:
输入第一行三个数 n , A , B。
接下里有 n 行,每行两个数 v_i , w_i 依次表示每个物品的体积和价值。


输出描述:
输出一个数,最大价值
示例1

输入

5 10 50
3 3
7 4
4 7
49 50
2 2

输出

60

说明

用一号袋子装1号和3号物品,之后收起一号袋子,用二号袋子装4号物品。 
#思路是分别使用两个袋子独立地做一遍,这个时候变成简单的01问题,需要注意的是袋子2从后往前遍历物品。
#做的时候用一个ans数组记录每个位置i时候,两个袋子分别的最大价值,
#最后遍历i,找到一个节点i使得
ansA[i]+ansB[i+1]最大,i节点换袋子

import
sys

n , A , B = list(map(int,input().split()))
#print(n,A,B)
values = []
weights = []
for line in sys.stdin:
    wi,vi = list(map(int,line.split()))
    values.append(vi)
    weights.append(wi)

dpA = [0]*(A+1)
ansA = [0]*(n+1)

dpB = [0]*(B+1)
ansB = [0]*(n+1)

for i in range(n):
    for j in range(A,weights[i]-1,-1):
        dpA[j] = max(dpA[j],dpA[j-weights[i]]+values[i])
    ansA[i] = dpA[A]

for i in range(n-1,-1,-1):
    for j in range(B,weights[i]-1,-1):
        dpB[j] = max(dpB[j],dpB[j-weights[i]]+values[i])
    ansB[i] = dpB[B]

res = 0
for i in range(n):
    res = max(res,ansA[i]+ansB[i+1])
# print(ansA)
# print(ansB)
print(res)

编辑于 2024-04-14 15:42:47 回复(0)

问题信息

难度:
1条回答 1869浏览

热门推荐

通过挑战的用户

查看代码