7-7 硬币找钱问题 (10 分)(思路+详解+double类型数据的处理)Come baby!!!!!!!!!!!!!!!!!!!!
一:題目
設有6 種不同面值的硬幣,各硬幣的面值分別為5 分,1 角,2 角,5 角,1 元,2元。現要用這些面值的硬幣來購物。在購物中希望使用最少個數硬幣。例如,1 次購物需要付款0.55 元,如果沒有5 角的硬幣,只好用22角+11角+1*5分 共4 枚硬幣來付款。
對于給定的各種面值的硬幣個數和付款金額,計算使用硬幣個數最少的交易方案。
輸入格式:
輸入數據有若干組,第一行給出一個整數n表示輸入數據的組數。
以下n行每一行有6 個整數和1個有2 位小數的實數。分別表示可以使用的各種面值的硬幣個數和付款金額。
輸出格式:
輸出每組數據的最少硬幣個數。如果不可能完成交易,則輸出“impossible”。
輸入樣例:
2 2 4 2 2 1 0 0.95 2 4 2 0 1 0 0.55輸出樣例:
4 4二:思路
思路:
1.map容器進行存儲 鍵值為面值(0.05,0.1,0.2,0.5,1,2) 關鍵值為對應的硬幣個數
2.將付款金額跟面值進行比較,找到剛好大于其面值的銀幣,并判斷其個數是否有無,
1>:如果其個數為0就繼續往下尋找銀幣,直到銀幣個數不為0為止
2>:如果其個數不為0的話那么我們就選擇 小于 付款金額的 銀幣數 并記錄個數
付款金額 = 付款金額 - 面值*銀幣數;
當付款金額小于面值的時候繼續往下尋找更小的面值
當銀幣數不夠了也是往下繼續尋找最小隱蔽數
3.如果最后的付款金額不為0,那么就是 impossible
測試數據:2
2 4 2 2 1 0 0.95
2 4 2 0 1 0 0.55
4.注意處理數據中的小數問題,因為double 存的數據和真實的并不一樣
eg :比如存入的是0.95 其實是0.9499999999182,那么當數據剩下0.0499909
那么它和0.05就無法比較了
三:關于處理double類型數據的精度問題
1.問題展示
問題描述:我們明明輸入的是double類型的 0.95 但通過調試我們發現其實他是 0.949999999,
2.回歸本題
本題但這中的測試用例1中有0.95這個付款金額,那么我們選擇銀幣的時候,會選擇一個 0.5,兩個0.2,那么還剩0.05,
剩下0.05是我們希望的正常情況,但是通過上方的演示,我們發現其是真實的值是小于0.05的,那么這樣的話就會影響我們計算銀幣的個數,因為統計不到0.05的銀幣個數
3.解決問題
本題當中自我感覺很開竅的地方,我們給付款金額加上0.00001,這樣就能保證我的數據最起碼是大于面值的,最后的余額再跟0.00001比較,如果小于其就是可以完全換成金幣個數的。注意這里不能是等于0.00001,因為確實是兩個數不相等,而且即便你將調試顯示的數抄上去都不行!!!
四:上碼
/**思路:1.map容器進行存儲 鍵值為面值(0.05,0.1,0.2,0.5,1,2) 關鍵值為對應的硬幣個數2.將付款金額跟面值進行比較,找到剛好大于其面值的銀幣,并判斷其個數是否有無,1>:如果其個數為0就繼續往下尋找銀幣,直到銀幣個數不為0為止2>:如果其個數不為0的話那么我們就選擇 小于 付款金額的 銀幣數 并記錄個數 付款金額 = 付款金額 - 面值*銀幣數;當付款金額小于面值的時候繼續往下尋找更小的面值當銀幣數不夠了也是往下繼續尋找最小隱蔽數3.如果最后的付款金額不為0,那么就是 impossible 測試數據:22 4 2 2 1 0 0.952 4 2 0 1 0 0.55 4.注意處理數據中的小數問題,因為double 存的數據和真實的并不一樣eg :比如存入的是0.95 其實是0.9499999999182,那么當數據剩下0.0499909那么它和0.05就無法比較了 */#include<bits/stdc++.h>using namespace std;int res(vector<double>& v){map<double,double>m;map<double,double>:: reverse_iterator t;int length = v.size();float pay = 0.00001; //付款金額 int cnt = 0;//統計銀幣個數 for(int i = length - 1; i >= 0; i--){if(i == 0) m[0.05] = v[i];if(i == 1) m[0.1] = v[i];if(i == 2) m[0.2] = v[i];if(i == 3) m[0.5] = v[i];if(i == 4) m[1] = v[i];if(i == 5) m[2] = v[i]; if(i == 6) pay += v[i];}for(t = m.rbegin(); t != m.rend(); t++){if(pay >= t->first && t->second != 0){//如果付款金額大于其面值 并且該面值銀幣數不為0 for(int i = 0; i < t->second; i++){if(pay >= t->first){//這里確保每次的付款金額均大于面值 pay = pay - t->first;cnt++; }else{break;}}} }//cout << cnt;// cout << pay << endl;//0.00999999139 if(pay <= 0.001){return cnt;// cout << "wyj";}return -1; }int main(){int n;cin >> n;for(int i = 0; i < n; i++){vector<double>v;for(int i = 0; i < 7; i++){double nums;cin >> nums;v.push_back(nums);}int ans = res(v);if(ans == -1){cout << "impossible" << endl;}else{cout << ans << endl;}} } //2//2 4 2 2 1 0 0.95//2 4 2 0 1 0 0.55//////1//2 4 2 2 1 0 0.95//1//2 4 2 2 1 0 0.05////1//2 4 2 2 1 0 0.95五:知識速遞(如果對map容器不熟悉的兄弟們可以了解下)
map的逆序遍歷
map的基本用法
又得嘮叨一句 記得加油 寶!!!!!!!!!!!!!!!!!!!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的7-7 硬币找钱问题 (10 分)(思路+详解+double类型数据的处理)Come baby!!!!!!!!!!!!!!!!!!!!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 减肥什么时候吃西红柿最好
- 下一篇: 7-6 区间覆盖 (10 分)(思路+详