动态规划背包问题篇

1、装箱问题

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30=,每个物品有一个体积(正整数)。要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

(注意点:一维逆序)
for(int i=0;i<n;i++)
	{
		scanf("%d",&w[i]);
		for(int j=V;j>=w[i];j--)
		{
			if(opt[j-w[i]]+w[i]>opt[j])
			{
				opt[j]=opt[j-w[i]]+w[i];
			}
		}
	}
	
	printf("%d\n",V-opt[V]);

2、砝码称重

设有1g、2g、3g、5g、10g、20g的砝码各若干枚(其总重<=1000),用他们能称出的重量的种类数。
(注意点:在利用一个数组vis来记录种类数,种类数不存在重复的情况)
for(int i=0;i<k;i++)
	{
		for(j=1000;j>=v[i];j--)
		{
			if(opt[j-v[i]]+v[i]>opt[j])
			{
				opt[j]=opt[j-v[i]]+v[i];
				if(vis[opt[j]]==0)
				{
					count++;
					vis[opt[j]]=1;
				}
			}
		}
	}
	printf("%d",count);

3、 挖地雷问题

在一个地图上有N个地窖(N<=20),每个地窖中埋有一定数量的地雷。同时,给出地窖之间的连接路径。当地窖及其连接的数据给出之后,某人可以从任一处开始挖地雷,然后可以沿着指出的连接往下挖(仅能选择一条路径),当无连接时挖地雷工作结束。设计一个挖地雷的方案,使某人能挖到最多的地雷。
(注意点:只看连通的路径,利用path来跟踪,利用max来记录最大)
opt[n]=w[n];
	for(int i=n-1;i>=1;i--)
	{
		opt[i]=w[i];
		for(int j=n;j>=i+1;j--)
		{
			
			if(s[i][j]==1)
			{
				if(w[i]+opt[j]>opt[i])
				{
					opt[i]=w[i]+opt[j];
					if(max<opt[i])
					{
						max=opt[i];
						max2=i;
					}
					path[i]=j;
				}
				
			}
		}
	}
	int i=max2;
	printf("%d",max2);
	while(path[i]!=0)
	{
		printf("->%d",path[i]);
		i=path[i];
	}
	printf("\n");
	printf("%d\n",max);

4、Money Systems问题

传统地,一个货币系统是由1,5,10,20 或 25,50, 和 100的单位面值组成的。母牛想知道有多少种不同的方法来用货币系统中的货币来构造一个确定的数值
(注意点:要知道一个数值有多少种方法表示,正序,opt[j]=opt[j-value[i]]+opt[j];)
	sort(value,value+V);
	opt[0]=1;
	for(int i=0;i<V;i++)
	{
		for(int j=value[i];j<=N;j++)
		{
			
				opt[j]=opt[j-value[i]]+opt[j];
		}
	}
	printf("%lld\n",opt[N]);

5、新年趣事之打牌

过年的时候,大人们最喜欢的活动,就是打牌了。xiaomengxian不会打牌,只好坐在一边看着。这天,正当一群人打牌打得起劲的时候,突然有人喊道:“这副牌少了几张!”众人一数,果然是少了。于是这副牌的主人得意地说:“这是一幅特制的牌,我知道整副牌每一张的重量。只要我们称一下剩下的牌的总重量,就能知道少了哪些牌了。”大家都觉得这个办法不错,于是称出剩下的牌的总量,开始计算少了哪些牌。由于数据量比较大,过了不久,大家都算得头晕了。这时,xiaomengxian大声说:“你们看我的吧!”于是他拿出笔记本电脑,编出了一个程序,很快就把缺少的牌找了出来。如果是你遇到了这样的情况呢?你能办到同样的事情吗?
(注意点:不存在!=的情况,所以if(opt[j]==0)path[j]=i; opt[j]=opt[j-s[i]]+opt[j]来标记表示opt[i]==1则i可以被表示出来)
	opt[0]=1;
	for(int i=1;i<=M;i++)
	{
		for(int j=V;j>=s[i];j--)
		{


			if(opt[j]<opt[j-s[i]])
			{
				if(opt[j]==0)
				path[j]=i;
				opt[j]=opt[j-s[i]]+opt[j];
			}	
		}
	}
	int sum=270,i=0;
	while(sum>0)
	{
		sor[i]=path[sum]+1;
		sum=sum-s[path[sum]];
		i++;
	}
	sort(sor,sor+i);
	for(int j=0;j<i;j++)
	{
		printf("%d ",sor[j]);
	}
	printf("\n");


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值