农夫买东西(多重背包+完全背包)

大致题意:有一个农夫,想要买东西,农夫有面值不同的钱有限张数。找钱的老板面值不同的钱有无限张。求买东西农夫付钱花的张数和老板找钱的张数的和最小张数。
题解:农夫其实就是多重背包。
老板其实就是完全背包。
设dp数组dp1[i]表示价值为i的时候,最少的硬币个数。

#include< iostream>
#include< cstdio>
#include< cstring>
#include< cmath>
#include< iomanip>
#define N 150
#define M 20000
#define inf 0x3f3f3f3f
using namespace std;
int n,m,ans=inf;
int w[N],num[N];
int f1[M],cnt[M],f2[M];
int main()
{
int i,j,k;
while(~scanf("%d%d",&n,&m))
{
for(i=1;i<=n;i++)
scanf("%d",&w[i]);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
memset(f1,0x3f,sizeof(f1));
memset(f2,0x3f,sizeof(f2));
f1[0]=f2[0]=0;
for(i=1;i<=n;i++)///钱币不同面值
{
memset(cnt,0,sizeof(cnt));
for(j=w[i];j<=10005;j++)
{
if(f1[j]>f1[j-w[i]]+1&&cnt[j-w[i]]<num[i])///多重背包求农夫最小张数
{
f1[j]=f1[j-w[i]]+1;
cnt[j]=cnt[j-w[i]]+1;
}
f2[j]=min(f2[j],f2[j-w[i]]+1);///完全背包老板最小张数
}
}
for(i=m;i<=10005;i++)///求和最小数量
{
ans=min(ans,f1[i]+f2[i-m]);
}
if(ans>=10005)printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}

发布了23 篇原创文章 · 获赞 0 · 访问量 317

猜你喜欢

转载自blog.csdn.net/qq_45762392/article/details/105715641
今日推荐