WUSTOJ 1311: 开心的金明(Java)动态规划-01背包

题目链接:🔗1311: 开心的金明

Description

金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N元(可以等于N元)的前提下,使每件物品的价格与重要度的乘积的总和最大。

设第j件物品的价格为v[j],重要度为w[j],共选中了k件物品,编号依次为j1j2,……,jk,则所求的总和为:

v[j1] * w[j1] + v[j2] * w[j2] + … + v[jk] * w[jk]。(其中*为乘号)

请你帮助金明设计一个满足要求的购物单。

Input

多组测试数据

输入 的第1行,为两个正整数,用一个空格隔开:

N m

(其中N(<30000)表示总钱数,m(<25)为希望购买物品的个数。)

从第2行到第m + 1行,第j行给出了编号为j - 1的物品的基本数据,每行有2个非负整数

v p

(其中v表示该物品的价格(v<=10000),p表示该物品的重要度(1~5))

Output

每组输出只有一个正整数,为不超过总钱数的物品的价格与重要度乘积的总和的最大值(<100000000)。

Sample Input

1000 5
800 2
400 5
300 5
400 3
200 2

Sample Output

3900

分析💬

WUSTOJ 1308: 采药(Java)动态规划-01背包是同样的问题,唯一的区别就是,这里的价值是物品的价格与重要度的乘积。典型的01背包问题。

先来解释一下代码中的value[][]这个二维数组。它表示的是物品的价值(价值=价格×重要度)。

value[i][j] = k表示有j元的情况下,选择完前i个物品后,能得到的最大价值(也就是Output描述的内容),当然这i个物品不一定都买。

关键在于这条语句,不买第i件物品和买第i件物品,谁的价值大
value[i][j] = Math.max(value[i - 1][j], value[i - 1][j - price] + price * importance)

代码💻

/**
 * Time 237ms
 * @author wowpH
 * @version 1.0
 * @date 2019年6月18日下午6:01:57
 * Environment:	Windows 10
 * IDE Version:	Eclipse 2019-3
 * JDK Version:	JDK1.8.0_112
 */

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

public class Main {
	private Scanner sc = new Scanner(new InputStreamReader(System.in));
	private int totalMoney, itemsNumber;// 总金钱,物品数量
	private Items[] items;// 物品
	private int[][] value;// 价值,价值=价格×重要度

	public Main() {
		while (sc.hasNext()) {
			init();// 输入并初始化
			solve();// 顺推结果
			System.out.println(value[itemsNumber][totalMoney]);
		}
		sc.close();
	}

	private void init() {
		totalMoney = sc.nextInt();
		itemsNumber = sc.nextInt();
		items = new Items[itemsNumber + 1];// 下标从1开始
		items[0] = new Items();
		for (int i = 1; i <= itemsNumber; ++i) {
			items[i] = new Items();
			items[i].price = sc.nextInt();
			items[i].importance = sc.nextInt();
		}
		value = new int[itemsNumber + 1][totalMoney + 1];// 下标从1开始
	}

	private void solve() {
		int temp;
		for (int i = 1; i <= itemsNumber; ++i) {// itemsNumber个物品
			for (int j = 1; j <= totalMoney; ++j) {
				if (j < items[i].price) {// 钱不够,第i个物品不选择
					value[i][j] = value[i - 1][j];
				} else {
					// 第i个物品的价值
					temp = items[i].price * items[i].importance;
					// 加上前面i-1个选择后的物品的价值
					temp += value[i - 1][j - items[i].price];
					// 选取价值较大的那种
					value[i][j] = Math.max(value[i - 1][j], temp);
				}
			}
		}
	}

	public static void main(String[] args) {
		new Main();
	}
}

class Items {// 物品
	int price;// 价格
	int importance;// 重要度
}

版权声明

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

posted @ 2019-06-18 22:51  wowpH  阅读(317)  评论(0编辑  收藏  举报