算法动态规划--日常购物(根据0-1背包问题改编的问题)

问题描述:小明今天很开心,因为在家买的新房子即将拿到钥匙。新房里面有一间他自己专用的、非常宽敞的房间。让他更高兴的是,他的母亲昨天对他说:“你的房间需要购买什么物品?怎么布置,你说了算,只要他们的价格总和不超过N元钱”。小明今天早上开始预算,但他想买太多的东西,肯定会超过母亲的N元限额。因此,他把对每件物品的渴望程度,分为5等级:用整数1->5表示,第5等表示最想要。他还从互联网上找到了每件商品(所有整数)的价格。他希望在不超过N元(可能等于N元)的情况下,将每件商品的价格与效益度的乘积的总和最大化.
设第j件物品的价格为p[j],重要度为w[j],其选中的k件商品,编号依次为j1,j2,……,jk,则所求的总和为:
p[j1]×w[j1]+p[j2]×w[j2]+ …+p[jk]×w[jk]。
请帮小明设计一个符合要求的购物清单。
其中N=2000,K=6
p[1]=200 w[1]=2
p[2]=300 w[2]=2
p[3]=600 w[3]=1
p[4]=400 w[4]=3
p[5]=1000 w[5]=4
p[6]=800 w[6]=5

参考书中的0-1背包问题的伪码编写:

#include <stdio.h>
#include <stdlib.h>
void Knapsack(int *v,int *w,int c,int n,int *m[] )
{ int jMax=(w[n]-1)<c?w[n]-1:c;
      for(int j=0;j<=jMax;j++)
	  	m[n][j]=0;
	  for(int j=w[n];j<=c;j++)
	 	m[n][j]=v[n];
	  for(int i=n-1;i>1;i--){
	 	jMax=(w[i]-1)<c?w[i]-1:c;
	 for(int j=0;j<=jMax;j++)
	 	m[i][j]=m[i+1][j];
	 for(int j=w[i];j<=c;j++){
	 	if(m[i+1][j]>(m[i+1][j-w[i]]+v[i])){
		 	
		 	m[i][j]=m[i+1][j];
		 }
		 else
		 m[i][j]=m[i+1][j-w[i]]+v[i];
	 }
	 	
	 }	
	 m[1][c]=m[2][c];
	 if(c>=w[1]){
	 	
	 	m[1][c]=m[1][c]>(m[2][c-w[1]]+v[1])?m[1][c]:m[2][c-w[1]]+v[1];
	 }
	
}
void Traceback(int *m[],int *w,int c,int n,int *x)
{
	for(int i=1;i<n;i++){
		if(m[i][c]==m[i+1][c]){
			x[i]=0;
		}
		else
		{
			x[i]=1;
			c-=w[i];
		}
	}
	x[n]=(m[n][c])?1:0;
}
int main (){
  int n,k;int *p,*w,*q;
  scanf("%d %d",&n,&k);
  p=(int *)malloc((k+1)*sizeof(int));
  w=(int *)malloc((k+1)*sizeof(int));
  q=(int *)malloc((k+1)*sizeof(int));
  for(int i=1;i<=k;i++){
  	scanf("%d %d",&p[i],&w[i]);
  }
  for(int i=1;i<=k;i++){
    	q[i]=p[i]*w[i];
    }
  int *m[n+1];
  for(int i=0;i<=n;i++){
  	m[i]=(int *)malloc((n+1)*sizeof(int ));
  }
 Knapsack(q,p,n,k,m);
 printf("%d \n",m[1][n]);
 int *x;
 x=(int *)malloc((n+1)*sizeof(int));
 Traceback(m,p,n,k,x);
 for(int i=1;i<=n;i++){
 	if(x[i]==1){
	 	printf("%d ",i);
	 }
 }
	return 0;
	
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
买书问题 dp实现 题目:买书 有一书店引进了一套书,共有3卷,每卷书定价是60元,书店为了搞促销,推出一个活动,活动如下: 如果单独购买其中一卷,那么可以打9.5折。 如果同时购买两卷不同的,那么可以打9折。 如果同时购买三卷不同的,那么可以打8.5折。 如果小明希望购买第1卷x本,第2卷y本,第3卷z本,那么至少需要多少钱呢?(x、y、z为三个已知整数)。 1、过程为一次一次的购买,每一次购买也许只买一本(这有三种方案),或者买两本(这也有三种方案), 或者三本一起买(这有一种方案),最后直到买完所有需要的书。 2、最后一步我必然会在7种购买方案中选择一种,因此我要在7种购买方案中选择一个最佳情况。 3、子问题是,我选择了某个方案后,如何使得购买剩余的书能用最少的钱?并且这个选择不会使得剩余的书为负数 。母问题和子问题都是给定三卷书的购买量,求最少需要用的钱,所以有"子问题重叠",问题中三个购买量设置为参数, 分别为i、j、k。 4、的确符合。 5、边界是一次购买就可以买完所有的书,处理方式请读者自己考虑。 6、每次选择最多有7种方案,并且不会同时实施其中多种,因此方案的选择互不影响,所以有"子问题独立"。 7、我可以用minMoney[i][j][k]来保存购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱。 8、共有x * y * z个问题,每个问题面对7种选择,时间为:O( x * y * z * 7) = O( x * y* z )。 9、用函数MinMoney(i,j,k)来表示购买第1卷i本,第2卷j本,第3卷k本时所需的最少金钱,那么有: MinMoney(i,j,k)=min(s1,s2,s3,s4,s5,s6,s7),其中s1,s2,s3,s4,s5,s6,s7分别为对应的7种方案使用的最少金钱: s1 = 60 * 0.95 + MinMoney(i-1,j,k) s2 = 60 * 0.95 + MinMoney(i,j-1,k) s3 = 60 * 0.95 + MinMoney(i,j,k-1) s4 = (60 + 60) * 0.9 + MinMoney(i-1,j-1,k) s5 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s6 = (60 + 60) * 0.9 + MinMoney(i-1,j,k-1) s7 = (60 + 60 + 60) * 0.85 + MinMoney(i-1,j-1,k-1)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值