枚举算法:
**定义:
根据提出问题,列出该问题的所有可能的解,并在逐一列出的过程中,检验每个可能解是否是问题的真正解(如果是,则采纳这个解,否则继续判断下一个)。
**应用:
枚举法往往适合解决较简单的题目,这类题目的特点:
1)枚举范围是有穷的;
2)检验条件是确定的;
**代码结构:
枚举范围循环+条件判断语句
Tips:
在程序中,可以通过多层for循环的方式来实现枚举多个变量。
例子1:年龄判断
完整代码
#include<iostream>
using namespace std;
int main(){
int tot=0;//记录可能解的个数
for(int i=10;i<=99;i++){//枚举年龄的范围
if(i-(i%10*10+i/10)==27){//判断条件 //%取余时取个位数,/取最高位数
tot++;
}
}
cout<<tot<<endl;
return 0;
}
例子2:水仙花数
完整代码
#include<iostream>
#include<cmath>
using namespace std;
int main(){
int cnt=0;
for(int i=100;i<=999;i++){
double a=i%10;//获取个位数字;
double b=i%100/10;//获取十位数; //'/'去取最高位,'%'去取最低位
double c=i/100;//获取百位数字;
double num=pow(a,3)+pow(b,3)+pow(c,3);//double pow(double x,double y) x的y次幂
if(num==i){
cnt++;
cout<<num<<" ";
}
}
cout<<endl;
cout<<cnt;
return 0;
}
Tips:
1)本题结构:预处理+枚举+判断
2)用到了cmath头文件中的函数:pow(double x,double y) x的 y次幂 。
例子3:四叶玫瑰
完整代码
#include <iostream>
using namespace std;
int pow(int n) {
return n * n * n * n;
}
bool rose(int x){
//**分别为个、十、百、千位**
int a=x%10;
int b=x/10%10;
int c=x/100%10;
int d=x/1000;
return pow(a)+pow(b)+pow(c)+pow(d)==x;
}
int main() {
int n;
cin >> n;
if(n<1000||n>9999){
cout<<"error!";
} else {
for(int i=1000;i<=n;i++){
if(rose(i)){
cout<<i<<endl;
}
}
}
return 0;
}
例子4:滑雪课程设计
完整代码
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
int a[1005];
int main() {
freopen("ski.in", "r", stdin);
freopen("ski.out", "w", stdout);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int ans = 1e9; // 表示 10 的 9 次方,是一个很大的数
for (int low = 0; low + 17 <= 100; low++) {
int high = low+17;
int sum = 0;
for (int i = 0; i < n; i++) {
if (a[i] < low) {
sum += (low - a[i]) * (low - a[i]);
}
if(a[i]>high){
sum+=(high-a[i])*(high-a[i]);
}
// 这里需要添加合适的代码
}
if(sum<ans)ans=sum;// 这里需要添加合适的代码
}
cout << ans << endl;
return 0;
}
例子5:子数整除
完整代码
#include <iostream>
using namespace std;
int main() {
freopen("divide.in", "r", stdin);
freopen("divide.out", "w", stdout);
int k;
cin >> k;
bool ok = false;
for (int i = 10000; i <= 30000; i++) {
int a = i/100;
int b = i/10%1000;
int c = i%1000;
if (a % k == 0 && b % k == 0 && c % k == 0) {
ok = true;
cout << i << endl;
}
}
if (!ok) {
puts("No");
}
return 0;
}
例子6:(多个枚举变量)方程的解
完整代码
#include <cmath>
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
for(int a=0;a*a<=n;a++){
for(int b=a;a*a+b*b<=n;b++){//让b初始化为a,是因为题目的条件是a<=b<=c!!!
/*for(int c=b;a*a+b*b+c*c<=n;c++){
if(a*a+b*b+c*c==n){
cout<<a<<" "<<b<<" "<<c<<endl;
}
}*/
int c=sqrt(n-a*a-b*b);
if(c>=b&&a*a+b*b+c*c==n){
cout<<a<<" "<<b<<" "<<c<<endl;
}
}
}
return 0;
}
例子7:扔骰子
思路:
用到前面数组下标应用中的计数排序的思想。
完整代码
#include <cstdio>
#include <iostream>
using namespace std;
int cnt[100];
int main() {
freopen("dice.in", "r", stdin);
freopen("dice.out", "w", stdout);
int a, b, c;
cin >> a >> b >> c;
for (int i = 1; i <= a; i++) {
for (int j = 1; j <= b; j++) {
for (int k = 1; k <= c; k++) {
int temp=i+j+k;
cnt[temp]++;
}
}
}
int ans = 1;
for (int i = 1; i<=a+b+c; i++) {
if (cnt[ans]<cnt[i]) {
ans = i;
}
}
cout << ans << endl;
return 0;
}
例子8:回文数
完整代码
#include <iostream>
#include <cstdio>
using namespace std;
//bool k=false;
int main() {
freopen("palindrome.in", "r", stdin);
freopen("palindrome.out", "w", stdout);
int n,flag=0;//标志flag
cin >> n;
for(int i=10000;i<=99999;i++){
int a=i/10000;
int b=i/1000%10;
int c=i/100%10;
int d=i/10%10;
int e=i%10;
if(a==e&&b==d&&(n==(a*2+b*2+c))){
cout<<i<<endl;
flag=1;
}
}
for(int i=100000;i<=999999;i++){
int a=i/100000;
int b=i/10000%10;
int c=i/1000%10;
int d=i/100%10;
int e=i/10%10;
int f=i%10;
if(a==f&&b==e&&c==d&&(n==(a*2+b*2+c*2))){
cout<<i<<endl;
flag=1;
}
}
if(flag==0)
cout<<-1;
/*if(!ok){
cout<<-1<<endl;
}*/
return 0;
}
Tips:
本题用到了一个标志flag,其值初始化为0,当满足条件时,将其置为1。
例子9:和数
思路:
双重循环(游标移动),第三层循环(即最内层循环)计算并判断
完整代码
#include <iostream>
#include <cstdio>
using namespace std;
int a[105];
int main(){
freopen("sum.in", "r", stdin);
freopen("sum.out", "w", stdout);
int n,i,count=0;
cin>>n;
//int a[n];
for(i=0;i<n;i++){
cin>>a[i];
}
for(i=0;i<n;i++){
int flag=0;
for(int j=0;j<n;j++){
for(int k=0;k<n;k++){
if(a[i]==a[j]+a[k]&&k!=j){//自己+自己!=自己
flag=1;
count++;//同一个数可能有多组数相加可以得到
break;
}
}
if(flag==1)
break;
}
}
cout<<count;
return 0;
}