HDU - 5527 A - Too Rich (貪心&&dfs)
阿新 • • 發佈:2018-11-14
連結:
http://acm.hdu.edu.cn/showproblem.php?pid=5527
題意:
給出硬幣面值和數量,讓你用數量最多的硬幣湊出給定的數.
思路:
正反思考都行.
正面想就是要儘可能多的用面值少的硬幣,所以從面值大的開始考慮,假設把比它面值小的都選上後,看看需要補多少個當前面值硬幣.
反面就是想去掉儘量少的硬幣,使得剩下的剛好滿足要求.
正:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int val[11] = {0, 1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000}; ll sum[11];//字首和 int c[11]; int ans; void dfs(int rest, int index,int cnt)//rest 剩下的錢 index 當前處理的面值下標 cnt 數量 { if(rest < 0 ) return ; if(index == 0) { if(rest == 0) ans = max(ans,cnt); return ; } ll cur = max(rest - sum[index - 1],(ll)0); //減去價格小的硬幣價錢之和後可以由當前硬幣提供的價錢 int curnum = cur / val[index]; //可以由當前硬幣提供的數量 if(cur % val[index])//如果不能整出,那麼必然要加一 { curnum++; } if(curnum <= c[index]) dfs(rest - curnum * val[index], index - 1, cnt + curnum); curnum++; if(curnum <= c[index]) dfs(rest - curnum * val[index], index - 1, cnt + curnum); } int main() { int t,p; cin>>t; while(t--) { memset(sum,0,sizeof sum); ans = -1; cin>>p; for(int i = 1; i <= 10; i++) cin>>c[i]; for(int i = 1; i <= 10 ; i++) { sum[i] = sum[i-1] + val[i] * c[i]; } dfs(p,10,0); cout<<ans<<endl; } return 0; }
反:
# include <iostream> # include <cstdio> # include <cstring> using namespace std; typedef long long LL; const LL INF = 0x3f3f3f3f3f3f3f3f; LL a[]= {0,1,5,10,20,50,100,200,500,1000,2000}, b[13]; LL ans; void dfs(int cur, LL tot, LL cnt) { if(tot < 0) return; if(cur == 0) { if(tot == 0) ans = min(ans, cnt); return; } LL tmp = min((LL)b[cur], tot/a[cur]); dfs(cur-1, tot-tmp*a[cur], cnt+tmp); if(tmp) dfs(cur-1, tot-(tmp-1)*a[cur], cnt+tmp-1); } int main() { int t; scanf("%d",&t); while(t--) { LL tot = 0, sum = 0, all = 0; ans = INF; scanf("%lld",&sum); for(int i=1; i<=10; ++i) scanf("%lld",&b[i]), tot += a[i]*b[i], all += b[i]; if(tot < sum) { puts("-1"); continue; } dfs(10, tot-sum, 0); if(ans == INF) puts("-1"); else printf("%lld\n",all-ans); } return 0; }