题目:
现在假设你是个店员,为了方便/准确/最优的找零钱,你设计了一个程序.该程序应该实现如下功能: 第一行输入客户所给你金额 第二行输入客户消费的总金额 第三行输出应找的总零钱是多少 第四行输出各种面额的张数(总金额之和要与第三行的数相等,并且要求货币总张数是最少的方案输出) 注:为了简单,假设上述中的金额都是整数,现规定金额的面值为100,50,20,10,5,1元.并且假定客户的金额总是大于所需支付的总金额. 数据类型有int整数表示.
输入:
多组数据,
第一行输入一个整数(表示客户所付的金额),如100
第二行输入一个整数(表示商品的总计金额),如25
输出:
第一行输出 应找的零钱,如75
第二行输出 金额面值1张数1+金额面值2+张数2+…+金额面值N张数N=零钱数。(面值较大的零钱优先排在前面,如50元比20元大,应排在前面)
样例:
输入:
100
25
95
2
输出:
75
501+201+51=75
93
501+202+13=93
思路:问了一圈大佬们的思路都是贪婪,就我一个蒟蒻第一反应是dp,然后写了dp的方法,遇到了自己不能解决的bug(我好菜。下面会贴出dp的错误(划重点)代码,原因是因为每张钱只用了一次,大佬给我讲这个要用完全背包做,但我太菜了还没学会,学会再来补代码吧。贪婪的思路就很简单啦。
错误的dp做法:
#include<iostream>
#define minn 1e5
using namespace std;
int pay;//付的钱
int back;//找的钱
struct node{
int x;//面值
int y;//数量
}money[6]={100,0,50,0,20,0,10,0,5,0,1,0};
int dp[100001];//最少的数量
int main(){
while(cin>>pay>>back){
int sum=pay-back;
cout<<sum<<endl;
dp[0]=0;
for(int i=1;i<=sum;++i){
dp[i]=minn;
}
for(int i=0;i<6;++i){
for(int j=sum;j>=money[i].x;--j){
dp[j]=min(dp[j],dp[j-money[i].x]+1);
if(dp[j]==(dp[j-money[i].x]+1)){
money[i].y++;
}
}
}
for(int i=0;i<=sum;++i){
cout<<dp[i]<<endl;
}
}
return 0;
}
正确的贪婪做法:
#include<iostream>
using namespace std;
int pay,back;
int arr[6]={100,50,20,10,5,1};
int count[6];
int main(){
while(cin>>pay>>back){
int first=0;
int sum=pay-back;
cout<<sum<<endl;
for(int i=0;i<6;++i){
count[i]=sum/arr[i];
sum=sum%arr[i];
}
for(int i=0;i<6;++i){
if(count[i]!=0&&first==0){
first=1;
cout<<arr[i]<<"*"<<count[i];
}else if(count[i]!=0){
cout<<"+"<<arr[i]<<"*"<<count[i];
}
}
cout<<"="<<(pay-back);
cout<<endl;
}
return 0;
}