我的做法,一次多重背包得出dp[i]表示john凑够i的钱需要几张硬币,再一次完全背包得出店家的情况。
然后枚举john给的钱数。因为john给的钱上限比较难以确定,所以直接开了30000。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=1e2+9; int v[maxn],c[maxn],vv[maxn*15],cc[maxn*15]; int dp[2][31111]; int lon; int main() { int n,t; while(scanf("%d %d",&n,&t)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&v[i]); for(int i=1;i<=n;i++) scanf("%d",&c[i]); lon=0; for(int i=1,tmp;i<=n;i++) { tmp=c[i]; for(int j=1;j<=tmp;j*=2) { vv[++lon]=j*v[i]; cc[lon]=j; tmp-=j; } if(tmp) { vv[++lon]=tmp*v[i]; cc[lon]=tmp; } } memset(dp,50,sizeof(dp)); dp[0][0]=0; for(int i=0;i<=31000;i++) for(int j=1;j<=lon;j++) if(i+vv[j]<=31000) { dp[0][i+vv[j]]=min(dp[0][i+vv[j]],dp[0][i]+cc[j]); } dp[1][0]=0; for(int i=0;i<=31000;i++) for(int j=1;j<=n;j++) if(i+v[j]<=31000) dp[1][i+v[j]]=min(dp[1][i+v[j]],dp[1][i]+1); int ans=111111111; for(int i=t;i<=31000;i++) ans=min(ans,dp[0][i]+dp[1][i-t]); if(ans<111111111) cout<<ans<<endl; else printf("-1\n"); } return 0; }
作者:yrleep 发表于2013-8-27 19:04:22 原文链接
阅读:0 评论:0 查看评论