动态规划经典例子

题目描述:

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

样例输入
1000 5
800 2
400 5
300 5
400 3
200 2

样例输出
3900

思路介绍:
在写这个题之前我希望你们先点一下链接看一下这个关于采药的问题,这个问题和这个题的意思大致是和上面一样的,
就拿上面的例子来看吧
1000 5(限制条件)
800 2
400 5
300 5
400 3
200 2
我们首先建立一个二维数组array[6][2];如下所示:

000行
8002*8001行
4005*4002行
3005*3003行
4003*4004行
2002 *2005行

这是事先要完成的,然后我们可以再建立一个二维数组bb[ 5+1][1000+1 ]
如果bb[i][j]代表的意思是不超过j元钱,前i件物品可以取得的最大值
那么很明显bb[i][0]=0,bb[0][j]=0
假设Wj代表的是第j件物品的价值,Vj表示第j件物品的钱数,那么如果Wj>j的时候bb[i][j]=bb[i-1][j],因为时候第j件物品的价值已经超过了可容纳的价值了,所以等于bb[i-1][j],
如果Wj<j时候有两种结果,要么就是第j件物品放进去了,此时的bb[i][j]=bb[i-1][j-Vj]+Wj
如果不放进去的话,此时bb[i][j]=bb[i-1][j],而这种情况就是取最大值了,大致的思路就是这样的,最后只要输出bb[5][1000]就可以得到结果了。

代码如下:

public class Main2 {
		public static void main(String[] args) {
			Scanner m=new Scanner(System.in);
			int a=m.nextInt();
			int b=m.nextInt();
			
			int array[][]=new int[b+1][2];
			for(int i=1;i<array.length;i++)
				for(int j=0;j<array[i].length;j++)
					array[i][j]=m.nextInt();
			
			for(int i=1;i<array.length;i++)
					array[i][1]=array[i][1]*array[i][0];
			
						
			int sm[][]=new int[b+1][a+1];
			for(int i=0;i<a;i++)
				sm[0][i]=0;
			for(int k=0;k<b;k++)
				sm[k][0]=0;
			
			for(int i=1;i<sm.length;i++)
				for(int j=1;j<sm[i].length;j++)
					if(array[i][0]>j)
						sm[i][j]=sm[i-1][j];
					else
						sm[i][j]=max(sm[i-1][j],sm[i-1][j-array[i][0]]+array[i][1]);
			
			System.out.println(sm[b][a]);
		}

		public static int max(int i, int j) {
			// TODO Auto-generated method stub
			int max=i>j?i:j;
			return max;
		}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值