学习了一些特别的方法做简单的题,现在我们来复习一个快要被人遗忘的算法——穷举。
穷举是一种算法,字面意思指无穷地列举情况,直到满足条件为止。穷举也被称为枚举,枚举的字面意思指不断地循环,逐一尝试所有的情况,直到满足条件为止。穷举一般分为四种情况(题型),分别为a减1,b加1枚举法(或者是a加1,b减1枚举)、一层循环穷举、二层循环穷举、三层循环穷举。下面我来分别介绍这四种枚举法。
第一种,a减1,b加1枚举法(或者是a加1,b减1枚举)。总的意思就是说乙要给甲一块钱,乙是怎么给钱的呢?是不是乙减1,然后甲加1?没错。如果是a加1,b减1也同理。接下来看看常见题型:
某班学生分 2 组参加植树活动,甲组有 17 人,乙组有 25 人,后来由于需要,从甲组抽调了部分学生去乙组,结果乙组的人数是甲组的 2 倍,请问从甲组抽调了多少人去乙组?
这道题就是这样的枚举。代码我不多讲了,就像上面一样的过程。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a=17,b=25,sum=0;
while(1){
if(b/2 == a){
cout<<sum;
return 0;
}
else{
a--;
b++;
sum++;
}
}
return 0;
}
第二种,一层循环穷举。这种穷举对于新手有点难理解(毕竟我是新手的时候弄了半天都不知道含义),总的来说就是每次循环判断符不符合条件,如果符合条件就输出此枚举方案或计数器加1。
常见题型:
某动物饲养中心用X元专款购买小狗(每只A元)和小猫(每只B元)两种小动物。
要求专款专用,(至少猫狗各一),正好用完?请求出方案的总数。如没有请输出0。
上AC代码:
#include<iostream>
using namespace std;
int main() {
int a,b,c;
cin>>a>>b>>c;
int sum=0;
for(int i=1;i<=a/b;i++){
if((a-i*b)%c==0){
sum++;
}
}
cout<<sum-1;
return 0;
}
(万能的减1,千万别学我卡AC样例)
第三种,二层循环穷举。二层循环穷举与上面过程同理,就是多加了一层循环而已。
常见题型:
小明暑假来到恐龙园游玩,在恐龙园的礼物店里,有一些形形色色的小恐龙玩偶,小明想购买其中霸王龙和三角龙玩偶送给自己的5位好朋友。店员告诉小明,霸王龙玩偶一只需要x元,三角龙玩偶一只需要y元。 小明有n元,希望两种恐龙都能购买,购买的霸王龙的数量>=三角龙的数量,购买的总数要在5个或者5个以上(这样才够分),而且不能有钱剩下。
请你编程帮助小明输出所有可能的购买方案,每组方案占1行,先输出霸王龙的数量,再输出三角龙的数量(霸王龙的数量从少到多,三角龙的数量从多到少)。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a,b,c;
cin>>a>>b>>c;
for(int i=1;i<=a/b;i++){
for(int j=a/c;j>=1;j--){
if(b*i+c*j == a && i+j>=5 && i>=j){
cout<<i<<' '<<j<<'\n';
}
}
}
return 0;
}
第四种, 三层循环穷举。这种穷举方式更加复杂,一般不建议新手刷这种题。这种穷举方式也跟循环穷举的方式一样,过程都差不多,基本都一样。就是多加了一层循环而已。
常见题型:
公园准备在小山上种桃树、梨树、苹果树,为了美观,总共准备种 n 棵树( n>=6 且 n 一定是 6 的倍数),要求三种树都得有,且每种树的数量都得是偶数,桃树的数量不能比梨树的数量多,梨树的数量不能比苹果树的数量多。请问有这三种树的数量分别有哪些可能的组合方法,从少到多分别数出桃树、梨树、苹果数可能的数量组合,每行 1 个方案。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin>>n;
for(int i=2;i<=n;i+=2){
for(int j=2;j<=n;j+=2){
for(int k=2;k<=n;k+=2){
if(i<=j&&i<=k&&j<=k&&i+j+k == n){
cout<<i<<' '<<j<<' '<<k<<'\n';
}
}
}
}
return 0;
}
好了,以上就是穷举的应用。复习完穷举,你悟了吗(长脑子了吗)?