购买某种价格的物品最少需要几张人民币?
纸币一共有五种:
1元、5元、10元、20元和50元
要购买物品的价格为1~99元的整数:
① 购买每种价格的物品最少需要几张纸币?
② 随机购买一种物品,平均最少要几张纸币?
下面分别用 穷举法 和 贪心法 求解 :
(1)穷举法:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
using namespace std;
int main() {
//i:循环变量; n:循环次数; money:当前的物品价格;
//firstone~fifthone:对应纸币的张数;
int i, n, money, o, sum, average=0, firstone, secondone, thirdone, fourthone, fifthone, p, q, r, s, t, minimum;
//设置时间为随机数的种子
srand(time(NULL));
cout << "input five types of money: " << endl;
cout << "(increasing order please)" << endl;
cin >> p >> q >> r >> s >> t;
cout << "input test times:" << endl;
cin >> n;
for (i = 1; i <= n; i++) {
//用随机数映射到1~100作为当前商品的价格
money = rand() * 100 / (RAND_MAX +1) + 1;
o = money;
//设置初始值
sum = 0;
minimum = 1000;
firstone = 0;
secondone = 0;
thirdone = 0;
fourthone = 0;
fifthone = 0;
//用for循环嵌套的方式把所有的符合总价的纸币组合列出来,计算张数,每次计算出来,判断是不是最小张数,然后更新
for (firstone = 0; firstone <= (money / t); firstone++) {
for (secondone = 0; secondone <= (o - firstone * t); secondone++) {
for (thirdone = 0; thirdone <= (o - firstone * t - secondone * s); thirdone++) {
for (fourthone = 0; fourthone <= (o - firstone * t - secondone * s - thirdone * r); fourthone++) {
for (fifthone = 0; fifthone <= (o - firstone * t - secondone * s - thirdone * r -
fourthone * q); fifthone++) {
if (firstone * t + secondone * s + thirdone * r + fourthone * q + fifthone * p == money) {
sum = firstone + secondone + thirdone + fourthone + fifthone;
if (minimum > sum) minimum = sum;
//注意每算完一种价值的物品,相关变量都要清零!
sum = 0;
o = money;
}
}
}
}
}
}
average += minimum;
cout << money << " " << minimum << endl;
}
cout << (average / n) << endl;
return 0;
}
(2)贪心法:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
using namespace std;
int main() {
// 变量名含义与穷举法相同
int i, n, money, o, sum, average, firstone, secondone, thirdone, fourthone, fifthone, p, q, r, s, t;
average = 0;
srand(time(NULL));
cout << "input five types of money: " << endl;
cout << "(increasing order please)" << endl;
cin >> p >> q >> r >> s >> t;
cout << "input test times:" << endl;
cin >> n;
for (i = 1; i <= n; i++){
money = rand()*100/(RAND_MAX+1)+1;
o = money;
sum = 0;
//用来记录每种纸币的张数
firstone = 0;
secondone = 0;
thirdone = 0;
fourthone = 0;
fifthone = 0;
//面值从大到小考虑
if (o >= t) {
fifthone = o / t;
o %= t;
}
if (o >= s) {
fourthone = o / s;
o %= s;
}
if (o >= r) {
thirdone = o / r;
o %= r;
}
if (o >= q) {
secondone = o / q;
o %= q;
}
if (o >= p) {
secondone = o / p;
o %= p;
}
sum = firstone + secondone + thirdone + fourthone + fifthone;
average += sum;
cout << money << " yuan's products need " << sum << " pieces of RMB" << endl;
}
cout << (average / n) << endl;
return 0;
}
运行结果
① 如价格为 67 元,则需要 5 张纸币;
② 随机购买 1000 次,平均需要 4 张纸币;
思考:
① 两种方法的结果是否总是相同?
(试输入纸币的种类为1元、5元、16元、23元和33元)
② 贪婪法和穷举法的各自优劣?