Too Rich(貪心)
阿新 • • 發佈:2018-12-20
題意:
現在你有P元錢,有10種不同面值的硬幣,每種硬幣有一定的數量,求用盡量多的硬幣湊出P元錢,如果湊不出輸出“-1”。
題解:
- 一、貪心(反向) (可以看下:一位大佬十分詳細的題解)反向:求出所有硬幣的總價值(sum)- 所求的價值(P),問題轉化成用盡可能少的硬幣去湊出這個差值(sum-P);貪心思想:從面值大的硬幣開始,儘可能多地使用大面值硬幣;演算法核心:因為(2050)和(200500)不是整數倍的關係,所以不能直接貪心,那麼就需要轉化問題;當取偶數個50,可以用20拼湊出來,但取奇數個50時,用20是拼湊不出來的。 我們可以列舉以下四種情況: (50和500都是偶數個,不先取50和500) (50為奇數個,500為偶數個,即我們先取一個50) (50為偶數個,500為奇數個,即我們先取一個500) (50為奇數個,500為奇數個,即我們先取一個50和一個500) 之後對於50和500都成對地取,每次取50或500的時候就取偶數個。然後就可以用貪心了。
#include <set> #include <map> #include <cmath> #include <stack> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <sstream> #include <iomanip> #include <iostream> #include <algorithm> #define clr(str,x) memset(str,x,sizeof(str)) #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); #define INF 0x7fffffff #define maxn typedef long long int ll; using namespace std; int have[12],c[12],val[10]= {1,5,10,20,50,100,200,500,1000,2000}; int consthave[12]; int solve(int t) { int ans=0; for(int i=9; i>=0; i--) { if(i==4||i==7) { int temp = min(t/(2*val[i]),have[i]/2); ans += temp*2; t -= val[i] * 2 * temp; } else { int temp = min(t/val[i],have[i]); ans += temp; t -= val[i] * temp; } if(t==0) break; } if(t>0) return INF; else return ans; } int main() { //FRER() //FREW() int T,p; scanf("%d",&T); while(T--) { int sum=0,tol=0; scanf("%d",&p); for(int i=0; i<10; i++) { scanf("%d",&consthave[i]); sum+=consthave[i]*val[i]; tol+=consthave[i]; } sum-=p; if(sum<0) { printf("-1\n"); continue; } int ans = INF; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { memcpy(have,consthave,sizeof(consthave)); int t=sum; if(i) { if(have[4]) t-=50,have[4]--; else continue; } if(j) { if(have[7]) t-=500,have[7]--; else continue; } if(t>=0) ans=min(ans,solve(t)+i+j); } } if(ans==INF) printf("-1\n"); else printf("%d\n",tol-ans); } return 0; }
第二種貪心做法,有點類似搜尋。
#include <set> #include <map> #include <cmath> #include <stack> #include <queue> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <sstream> #include <iomanip> #include <iostream> #include <algorithm> #define clr(str,x) memset(str,x,sizeof(str)) #define FRER() freopen("in.txt","r",stdin); #define FREW() freopen("out.txt","w",stdout); #define INF 0x3f3f3f3f #define maxn typedef long long int ll; using namespace std; int have[10],val[]= {1,5,10,20,50,100,200,500,1000,2000}; int consthave[10]; int solve(int t) { int ans=0; for(int i=9; i>=0; i--) { if(i==4||i==7) { int temp = min(t/(val[i]*2),have[i]/2); ans += temp*2; t -= val[i] * 2 * temp; } else { int temp = min(t/val[i],have[i]); ans += temp; t -= val[i] * temp; } if(t==0) break; } if(t>0) return INF; else return ans; } int main() { //FRER() //FREW() int T,p; scanf("%d",&T); while(T--) { int sum=0,tol=0; scanf("%d",&p); for(int i=0; i<10; i++) { scanf("%d",&consthave[i]); sum+=consthave[i]*val[i]; tol+=consthave[i]; } sum-=p; if(sum<0) { printf("-1\n"); continue; } int ans = INF; for(int i=0; i<2; i++) { for(int j=0; j<2; j++) { memcpy(have,consthave,sizeof(consthave)); int t=sum; if(i) { if(have[4]) t-=50,have[4]--; else continue; } if(j) { if(have[7]) t-=500,have[7]--; else continue; } if(t>=0) ans=min(ans,solve(t)+i+j); } } if(ans==INF) printf("-1\n"); else printf("%d\n",tol-ans); } return 0; }