【枚举法】百钱百鸡2

题目描述

中国数学家张邱建(公元五世纪,其它资料不详),在他的《算经》中提出了著名的“百钱买百鸡”问题:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问翁、母、雏各几何?
你的任务是:根据给定的钱数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

问题提示

所有方案,第一优先级按公鸡的数量从小到大排列。

思路分析

枚举法的一些套路,确定以下内容:

  1. 枚举对象。有几个来几重循环
  2. 枚举范围。
  3. 判断条件。

根据题面信息,

  1. 三个未知的枚举对象:公鸡、母鸡和小鸡。
  2. 鸡的数量最多n只。
  3. 需要满足两个条件
    1. 总数为n
    2. 总的价格为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)\)的复杂度。该题目范围,显然会超时。需要进一步优化。

对于枚举法优化的几个思考方向:

  1. 减少枚举对象
  2. 剪枝
  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;
}
posted @ 2022-03-02 09:56  咸鱼爱学习  阅读(192)  评论(0编辑  收藏  举报