WUSTOJ 1320: 饭卡(Java)动态规划-背包

108 篇文章 0 订阅
80 篇文章 18 订阅
题目链接:?1320: 饭卡
参考:?hdu 2546 饭卡(经典dp)——H2oooooooooooooooooo

Description

武汉科技大学南苑食堂的饭卡有一种很诡异的设计,即在购买之前判断余额。如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够)。所以大家都希望尽量使卡上的余额最少。
某天,食堂中有n种菜出售,每种菜可购买一次。已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少。

Input

第一行为T,表示数据组数(1<=T<=100)

对于每组数据:
第一行为正整数n,表示菜的数量。n<=1000。
接着为n个正整数,表示每种菜的价格。价格不超过50。
然后为一个正整数m,表示卡上的余额。m<=1000。

Output

对于每组输入,输出一行,格式为:Case x: y
x表示测试数据的编号,从1开始。y表示卡上可能的最小余额。

Sample Input

3
1
50
5
10
1 2 3 2 1 1 2 3 2 1
50
2
3 2
4

Sample Output

Case 1: -45
Case 2: 32
Case 3: 4

分析?

背包问题已经接触过几次了。但是这道题目稍稍变化了一点点。当然这也是本题的关键点。

假设我们现在正在买最后一道菜,那么怎样使得最后的余额最少呢?

首先这个菜要最贵,这样才余额才最少。其次我们买之前余额也要尽量少。但是不能低于5元,否则无法购买。

如果 m 小于5的话,那就直接输出,一道菜都不能买。注意编号也要输出。

如果 m 大于5的话,我们只要存5元,然后用剩余的钱,在剩余的 (n - 1) 道菜中买的越多越好。

因此最终问题变成了:我有 (m - 5) 元,买 (n - 1) 道菜,怎样才能总消费最大化?这不就成了很容易的动态规划了吗?

代码

/**
 * Time 334ms
 * @author wowpH
 * @version 1.1
 * @date 2019年6月23日上午11:59:50
 * Environment:	Windows 10
 * IDE Version:	Eclipse 2019-3
 * JDK Version:	JDK1.8.0_112
 */

import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		Scanner sc = new Scanner(new InputStreamReader(System.in));
		int[] price, total;// 菜的价值,总消费
		int T, n, m;// 数据组数,菜的数量,卡的余额

		T = sc.nextInt();
		// 要输出测试数据编号k
		for (int k = 1; k <= T; ++k) {
			n = sc.nextInt();
			price = new int[n + 1];// 下标从1开始
			for (int i = 1; i <= n; ++i) {
				price[i] = sc.nextInt();
			}

			Arrays.sort(price, 1, n + 1);// 按照价格排序

			m = sc.nextInt();
			if (m < 5) {
				System.out.println("Case " + k + ": " + m);// 不足5元,直接输出
				continue;
			}

			m -= 5;// 至少要留5元,先减掉,到后面再加上来
			total = new int[m + 1];// 下标从1开始
			int temp;
			for (int i = 1; i < n; ++i) {// 前面n-1个菜
				for (int j = m; j >= price[i]; --j) {
					// 购买第i个菜后的总消费
					temp = total[j - price[i]] + price[i];
					// 总消费取“不购买”和“购买”第i个菜后较大的情况
					total[j] = Math.max(total[j], temp);
				}
			}

			System.out.print("Case " + k + ": ");// 测试数据编号
			// 加上保存的5元,再减去前面n-1个菜的总消费,再减去第n个菜的价格
			System.out.println(m + 5 - total[m] - price[n]);
		}
		sc.close();
	}
}

需要注意的是别忘了在最后加上5元。


版权声明

  1. 转载、参考、引用必须在首页添加如下文字:
    [WUSTOJ 1320: 饭卡(Java)动态规划-背包——wowpH](https://blog.csdn.net/pfdvnah/article/details/93385427)
  2. 代码原创,公开引用不能删除首行注释(作者,版本号,时间等信息);
  3. 如果有疑问欢迎评论区留言,尽量解答;
  4. 如果有错误,还望大侠评论区指正。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值