POJ-3260-The Fewest Coins

本文介绍了一种解决购物找零问题的方法,该问题要求计算最少需要使用多少张金币完成支付,涉及多重背包和完全背包两种算法。通过具体代码实现展示了如何在顾客支付和商家找零两个场景中应用这些算法。

这个题是说给你n种金币的面额以及他们的数量,并给你一个金额T,让你进行一个购物拿钱的计算,自己拿出的钱有数量限制,店主找钱的话则没有数量限制,让你算出要成功购买T元的东西至少需要拿出多少张钱。

由上述所说,自己拿出钱是一个多重背包,而店主找钱则是一个完全背包,进行相应的做即可

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=25010;
struct node
{
    int num;
    int val;
}a[11010];
int n,cur,m,v[110],c[110],dpa[maxn],dpb[maxn];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
	memset(dpb,0x3f,sizeof(dpb));
	memset(dpa,0x3f,sizeof(dpa));
	dpa[0]=dpb[0]=0;
	int mx=0;
	for(int i=0;i<n;i++)
	{
	    scanf("%d",&v[i]);
	    mx=max(mx,v[i]);
	}
	mx*=mx;
	cur=0;
	for(int i=0;i<n;i++)
	{
	    scanf("%d",&c[i]);
	    for(int j=0;(1<<j)<=c[i];j++)
	    {
		a[cur++]=(node){1<<j,(1<<j)*v[i]};
		c[i]-=1<<j;
	    }
	    if(c[i]>1)
		a[cur++]=(node){c[i],c[i]*v[i]};
	}
	for(int i=0;i<n;i++)
	    for(int j=v[i];j<=mx;j++)
		dpa[j]=min(dpa[j],dpa[j-v[i]]+1);
	for(int i=0;i<cur;i++)
	    for(int j=mx;j>=a[i].val;j--)
		dpb[j]=min(dpb[j],dpb[j-a[i].val]+a[i].num);
	int ans=0x7f7f7f7f;
	for(int i=m;i<=mx;i++)
	    ans=min(ans,dpb[i]+dpa[i-m]);
	printf("%d\n",ans==0x7f7f7f7f?-1:ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值