ALGO-31开心的金明(01背包)

资源限制

时间限制:1.0s   内存限制:256.0MB

问题描述

  金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间。更让他高兴的是,妈妈昨天对他说:“你的房间需要购买哪些物品,怎 么布置,你说了算,只要不超过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]。(其中*为乘号)
  请 你帮助金明设计一个满足要求的购物单。

输入格式

  输入文件 的第1行,为两个正整数,用一个空格隔开:
  N m
  (其中N(<30000)表示总钱 数,m(<25)为希望购买物品的个数。)
  从第2行到第m+1行,第j行给出了编号为j-1的物品的基本数据,每行有2个非负整数
  v p
  (其中v表示该物品的价格(v<=10000),p表示该物品的重要度(1~5))

输出格式

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

样例输入

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

样例输出

3900

思考:01背包问题,注意的点就是:在普通物品表上加一栏用来存储加权值,也就是重要度和价格的乘积,建立两张表,一张用来判断费用,一张用来对应存储加权值。因为有两张表,所以要同时对两张表进行操作,最后输出的是加权值表中的最后一项。还有一点就是,判断继续装包还是不装包的判断时,要根据加权值的大小进行判断,而不能用计费表中的值进行判断,因为计费表中的值越大代表剩余的费用越少,这就与我们的目的相悖。

//01背包问题
import java.util.*;

public class Main {

	public static void main(String [] args) {
		Scanner in=new Scanner(System.in);
		int N ,m;
		N=in.nextInt();//可以支配的总钱数
		m=in.nextInt();//预采购数量
		int[][] list=new int[m+1][4];//价格,重要度,加权值表
		int[][] cap=new int[m+1][N+1];//背包容量表
		int[][] res=new int[m+1][N+1];//结果表存放加权值
		for(int i=1;i<m+1;i++)//输入价格表
		{
			for (int j=1;j<3;j++)
			{
				list[i][j]=in.nextInt();//按照题目要求输入,第一列为价格,第二列为重要度
			}
		}
		for(int i=1;i<m+1;i++)//将加权之后的值记录进list的最后一列中
		{
			list[i][3]=list[i][1]*list[i][2];//价格和重要度相乘

		}
		
		for (int i=1;i<m+1;i++)//商品从第一个开始
		{
			for(int j=1;j<N+1;j++)//可承受价格从1开始递增
			{
				if(list[i][1]>j)//如果此时的商品价格超过可承受价格,则不进行购买,加权值等顺延上一个
				{
					cap[i][j]=cap[i-1][j];
					res[i][j]=res[i-1][j];
				}
				else
				{

					int value1=cap[i-1][j-list[i][1]]+list[i][1];//价格可以承受且继续购买物品
					int res1=res[i-1][j-list[i][1]]+list[i][3];//同上
					
					int value2=cap[i-1][j];//不在购买物品
					int res2=res[i-1][j];//同上
					if(res1>res2)//注意!!!要比较加权值的大小,使用加权值大的那一个
					{
						
						cap[i][j]=value1;
						res[i][j]=res1;
					}
					else 
					{
						res[i][j]=res2;
						cap[i][j]=value2;
					}
						
				}
			}
		}
		System.out.println(res[m][N]);//输出最后一个加权值,也就是在限额下最后一个商品执行完操作后的值
	}
	
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值