题目描述
中国数学家张邱建(公元五世纪,其它资料不详),在他的《算经》中提出了著名的“百钱买百鸡”问题:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问翁、母、雏各几何?
你的任务是:根据给定的钱数m,和买到的鸡数n,输出所有的方案。如果没有可行方案,输出None。
输入格式
只有两个整数m、n(0<m,n<10000) 。表示买鸡用的总钱数和总只数。
输出格式
若干行,每行3个数,表示一种可行方案,分别表示鸡翁、鸡母、鸡雏的数量。
样例输入1
100 100
样例输出1
0 25 75
4 18 78
8 11 81
12 4 84
问题提示
所有方案,第一优先级按公鸡的数量从小到大排列。
思路分析
枚举法的一些套路,确定以下内容:
- 枚举对象。有几个来几重循环
- 枚举范围。
- 判断条件。
根据题面信息,
- 三个未知的枚举对象:公鸡、母鸡和小鸡。
- 鸡的数量最多n只。
- 需要满足两个条件
- 总数为n
- 总的价格为m
第一版框架
for(int i=0;i<=n;i++){//枚举公鸡的可能数量
for(int j=0;j<=n;j++){//枚举母鸡的可能数量
for(int k=0;k<=n;k++){//枚举小鸡的可能数量
if(k%3==0&&(i+j+k==n)&&(5*i+3*j+k/3==m)){//数量和钱满足要求
}
}
}
}
分析复杂度三重循环\(O(n^3)\)的复杂度。该题目范围,显然会超时。需要进一步优化。
对于枚举法优化的几个思考方向:
- 减少枚举对象
- 剪枝
- hash代替判断
根据数量关系,三种鸡加起来总共n只,那么当已经确定公鸡i,母鸡j时,小鸡的数量可等于\(n-i-j\)不用再循环枚举了。这样就减少了一重循环。
再根据钱的总价为m,那么公鸡最多就是买\(\frac{m}{5}\)只,母鸡最多就是买\(\frac{m}{3}\)只,不需要枚举到n,减少非必要的枚举。
第二版框架
for(int i=0;i<=m/5;i++){//枚举公鸡的可能数量
for(int j=0;j<=m/3;j++){//枚举母鸡的可能数量
int k=n-i-j;//计算小鸡的数量
if(k%3==0&&(5*i+3*j+k/3==m)){//钱满足要求
}
}
}
}
实现代码
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int m,n;
bool flag=false;
cin>>m>>n;
for(int i=0;i<=m/5;i++){//枚举公鸡的数量
for(int j=0;j<=m/3-i;j++){//枚举母鸡数量
int k=n-i-j;//计算小鸡的数量
if(k<0) break;//小鸡数量小于0 不符合要求
if(k%3==0&&5*i+3*j+k/3==m){//看钱的总数是否是m
flag=true;//标记有存在方案
cout<<i<<" "<<j<<" "<<k<<endl;
}
}
}
if(!flag){//没有组合输出None
cout<<"None";
}
return 0;
}