题目:http://acm.split.hdu.edu.cn/showproblem.php?pid=5527
题意:给你1,5,10,20,50,100,200,500,1000,2000面额的硬币,问凑成p金额最多可以用多少硬币
参考:http://blog.csdn.net/tc_to_top/article/details/49634405
要尽可能用的多的硬币,但首先要保证能凑到,所以我们从大面额开始决策
对于当前面额要选几张,我们知道它前面最大能凑到多少,那么当前至少要选几张就确定了
如果不能刚好凑到,那么就得多选一张当前面额
因为20,50和200,500不能整除,所以有时需要多选一张
#include<cstdio> #include<iostream> #include<cmath> #include<queue> #include<map> #include<set> #include<stack> #include<stack> #include<string> #include<sstream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int f[15]={0,1,5,10,20,50,100,200,500,1000,2000}; ll s[15]; int a[15]; int ans; void dfs(int now,int i,int cnt) { if (now<0) return; if (i==0) { if (now==0) ans=max(ans,cnt); return; } ll t=max(now-s[i-1],0LL); int num=t/f[i]; if (t%f[i]) num++; if (num<=a[i]) dfs(now-num*f[i],i-1,cnt+num); num++; if (num<=a[i]) dfs(now-num*f[i],i-1,cnt+num); } int main() { int T; scanf("%d",&T); while(T--) { int p; scanf("%d",&p); s[0]=0; for(int i=1;i<=10;i++) { scanf("%d",&a[i]); s[i]=s[i-1]+1LL*a[i]*f[i]; } ans=-1; dfs(p,10,0); printf("%d ",ans); } return 0; }