问题描述
币值统计问题:已知各种币值(如100、70、50、20、10、5、2、1),对于给定的整数(比如140),确定每种币值的张数,使得所需的总张数最少。
算法分析
- 算法思想:首先对给定的币值进行降序排列,保证每次选择的币值都是最大的,使最终所需要的总张数最小。从面额最大的币种开始遍历,使用贪心算法的思路,对于每个币值,都尽可能多地选取,直到不能够被凑出目标金额为止。其次初始化一个数组count[ ]用来记录每种币值的张数。最后初始化变量num,用于记录所需要的总张数,即为所求解。另外,如果目标金额可以被凑出,则结束程序,否则再次输入币值种类进行分配,这也是贪心算法的局限所在。
- 算法实现:设计两个数组,其中,moneylist[ ]用来存放给定的面额种类,count[ ]用来存放每种币值需要的张数。
- 时间复杂度:进行币值从大到小排序时,使用选择排序的方法。外层的for循环进行n次,内层的for循环进行次,故时间复杂度为。
完整代码
#include <iostream>
using namespace std;
int num=0;//总张数
void alloc(int x){//币值分配
cout<<"请输入币值的种类数:";
int n;
int moneylist[n]={};//币值种类
cin>>n;
int count[n]={0};//张数
cout<<"请输入"<<n<<"种面值:";
for(int i=0;i<n;i++){
cin>>moneylist[i];
}
for(int i=0;i<n;i++){//币值由大到小排序
for(int j=i+1;j<n;j++){
if(moneylist[i]<moneylist[j]){//前一个元素小于后一个元素
int temp;
temp=moneylist[i];
moneylist[i]=moneylist[j];//大的元素向前移动
moneylist[j]=temp;
}
}
}
int temp=0;//临时存储
for(int i=0;i<n;i++){//分配币值
temp=x/moneylist[i];
count[i]+=temp;
x=x-moneylist[i]*temp;
num+=temp;
cout<<moneylist[i]<<"元的有"<<count[i]<<"张"<<endl;
}
if(x==0){//判断是否可以完全分配
cout<<"目标金额可被完全分配!"<<endl;
cout<<"所需要的总张数为:"<<num<<endl;
}
else{
cout<<"目标金额分配不完全,请重新输入目标金额及币值种类!"<<endl;
cout<<endl;
cout<<"请输入目标金额(整数):";
cin>>x;
alloc(x);
}
//cout<<"所需要的总张数为:"<<num<<endl;
}
int main(){
int n;
cout<<"请输入目标金额(整数):";
cin>>n;
alloc(n);
return 0;
}
886!