NUIST 9th 校赛 P4

NUIST 9th 校赛 P4

题目描述

每天我们都会思考一个令人纠结的难题:晚上吃什么。你打开手机想点个外卖,发现自己有一张满减优惠券快要过期了。
你选择了一家餐厅,这家餐厅一共有 N 道菜品,价格分别是 A1, A2, … , AN 元。只要消费满 X 元,就可以用掉这张优惠券。
你希望选择若干道 不同 的菜品,使得总价在不低于 X 元的同时尽量低。
为了用掉这张优惠券,你最少需要消费多少元?

输入描述

题目包含多组测试数据。第一行包括一个正整数 T,代表测试数据的组数。
接下来的输入,对于每组测试数据:

第一行包含两个整数 N 和 X (1 ≤ N ≤ 20, 1 ≤ X ≤ 100)
第二行包含 N 个整数 A1, A2, … , AN (1 ≤ Ai ≤ 100)

输出描述

对于每组测试数据,输出最少的消费。如果你把 N 道菜都买了还不能达到 X 元的优惠标准,输出 -1。

样例输入

2
10 50
9 9 9 9 9 9 9 9 9 8

3 30
9 9 9

样例输出

53

-1

这道题是一道DP。
状态转移方程 F[i][j] = min(f[i-1][j],f[i-1][j-value[i]] )+ value[i]
f[i][j] = min(f[i-1][j] ,value[i])
关键在于它是如何体现F[i][j] 一定不少于X元
把所有的值初始化为BigINT,j = 0 时 为 0,用递推思想理解即可。假设j不存在,那么j+value[i],也一定不存在,因为,前面的数无法到达j,j+value[i],也到达不了。理解了这个思想,很容易就想出:

	for(int i = 1;i<=n;i++){
			for(int j = 1;j<=x;j++){
				if(j>=a[i][j]){
					dp[i][j] = min(dp[i-1][j],dp[i-1][j-a[i]]+a[i]);
					
				}
				else{
					dp[i][j] = min(dp[i-1][j],a[i]);
					
				}
			}
		}

空间复杂度为O(nx)时间复杂度(nx)
但是空间可以做出优化

	for(int i = 1;i<=n;i++){
			for(int j = x;j>=1;j--){
				if(j>=a[i]){
					dp[j] = min(dp[j],dp[j-a[i]]+a[i]);
					
				}
				else{
					dp[j] = min(dp[j],a[i]);
					
				}
			}
		}

区别在于j要从后往前

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值