FJ要買價值爲V的東西,他又N種貨幣,第i種的幣值爲Vi,數量爲Ai,老闆每種貨幣都有無數個,求最少需要多少張貨幣完成交易(FJ付出的加上老闆找零用的)
先計算FJ付x元最少要幾張貨幣(多重揹包),然後計算找y元最少需要幾張貨幣(完全揹包),然後枚舉x-y=V對應的最小值
x和y的上限我開到15000就能過了,DISCUSS上有人說Vmax*Vmax就夠,不是很明白
代碼:
#include<iostream>
#include<memory.h>
#include<string>
#include<cstdio>
#include<algorithm>
#include<math.h>
#include<stack>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int MAX=15005;
const int inf=1<<29;
int dp1[MAX],dp2[MAX],val[105],used[MAX],a[MAX];
int main()
{
int i,j,k,V,n;
while(scanf("%d%d",&n,&V)!=EOF)
{
for(i=1;i<MAX;i++)
{
dp1[i]=dp2[i]=inf;
}
dp1[0]=dp2[0]=0;
for(i=1;i<=n;i++)
{
scanf("%d",&val[i]);
}
for(j=1;j<=n;j++)
scanf("%d",&a[j]);
for(i=1;i<=n;i++)
{
memset(used,0,sizeof(used));
for(j=val[i];j<MAX;j++)
{
if(dp1[j-val[i]]+1<dp1[j]&&used[j-val[i]]<a[i])
{
//cout<<j<<endl;
dp1[j]=dp1[j-val[i]]+1;
used[j]=used[j-val[i]]+1;
}
}
}
for(i=1;i<=n;i++)
{
for(j=val[i];j<MAX;j++)
{
dp2[j]=min(dp2[j],dp2[j-val[i]]+1);
}
}
int ans=inf;
for(i=V;i<MAX;i++)
{
ans=min(ans,dp1[i]+dp2[i-V]);
}
if(ans==inf)
ans=-1;
printf("%d\n",ans);
}
return 0;
}