题目链接:?1311: 开心的金明
Description
金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎么布置,你说了算,只要不超过N
元钱就行”。今天一早金明就开始做预算,但是他想买的东西太多了,肯定会超过妈妈限定的N
元。于是,他把每件物品规定了一个重要度,分为5等:用整数1~5表示,第5等最重要。他还从因特网上查到了每件物品的价格(都是整数元)。他希望在不超过N
元(可以等于N
元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
设第j
件物品的价格为v[j]
,重要度为w[j]
,共选中了k
件物品,编号依次为j1
,j2
,……,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;// 重要度
}
版权声明
- 转载、参考、引用必须在首页添加如下文字:
[WUSTOJ 1311: 开心的金明(Java)动态规划-01背包——wowpH](https://blog.csdn.net/pfdvnah/article/details/92798343)
- 代码原创,公开引用不能删除首行注释(作者,版本号,时间等信息)
- 如果有疑问欢迎评论区留言,尽量解答;
- 如果有错误,还望大侠评论区指正。