算法学习笔记——暴力求解之枚举

本文详细介绍了暴力求解中的枚举方法,并通过实例演示了如何运用枚举策略解决清华大学复试上机题中的三重循环、反序数、对称平方数、与7有关的数、百鸡问题和OldBill等问题。强调了在处理大枚举量时优化解法的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法学习笔记——暴力求解之枚举

枚举

枚举是指对每个可能的解进行逐一判断,直到找到符合题目要求的答案。枚举类的题目本身并不复杂,但在采取枚举策略之前,一定要好好的分析题目的枚举量,枚举量过大的时候,需要选择其他的解决方法。即使问题适合枚举,也要进行分析,以便通过减少部分无效的枚举来使程序更加的简洁和高效。

例题

一、abc(清华大学复试上机题)

题目

image-20240401213029881

三重循环解法
#include <iostream>
#include<cstdio>//标准输入输出,相当于stdio.h
using namespace std;

int main() {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= 9; j++) {
            for (int k = 0; k <= 9; k++) {
                if (100*i+110*j+12*k == 532) {
                    printf("%d %d %d\n",i,j,k);
                }
            }
        }
    }
}

image-20240401215330211

二、反序数(清华大学复试上机题)

题目

image-20240401215604973

一重循环解法
#include <iostream>
using namespace std;
 int R(int x){//求反序数
  int revx=0;
  while(x!=0){
  	revx *= 10;
  	revx += x%10;
  	x/=10;
  }
  return revx;
 }
int main() {
  for(int i=1000;i<=9999;i++){
  	if(i*9==R(i)){
	  	printf("%i\n",i);
	  }
  }
}
// 64 位输出请用 printf("%lld")

image-20240401223132395

四重循环解法
#include <iostream>
using namespace std;

int main() {
    int a, b, c, d;
    for (int a = 1; a <= 9; a++) {
        for (int b = 0; b <= 9; b++) {
            for (int c = 0; c <= 9; c++) {
                for (int d = 0; d <= 9; d++) {

                    int num1 = 1000 * a + 100 * b + 10 * c + d;
                    int num2 = 1000 * d + 100 * c + 10 * b + a;
                    if (9*num1 == num2) {
                        printf("%d\n", num1);
                    }


                }
            }
        }
    }
}
// 64 位输出请用 printf("%lld")

image-20240401222831633

三、对称平方数1(清华大学复试上机题)

题目

image-20240405214310992

解法
#include <iostream>
#include <cmath>  
using namespace std;
int R(int x) {
    int revx = 0;
    while (x != 0) {
        revx *= 10;
        revx += x % 10;
        x /= 10;
    }
    return revx;
}
int main() {
    for (int i = 0; i <= 256; i++) {
        if (pow(i,2) == R(pow(i,2))) {
            printf("%d\n", i);
        }
    }
}
// 64 位输出请用 printf("%lld")

image-20240405214408505

补充知识(cmath库)
#include <cmath> 
pow(a,b)       //a的b次方
sqrt(x)        //x的开平方,根号下的x
abs(n)         //整数n的绝对值
fabs(m)        //浮点数m的绝对值

习题

一、与7有关的数

题目

image-20240421210429889

我的解法
#include<iostream>
using namespace std;//cin,cout函数
int isseven(int n) {
    int m = n;
    if (n <= 0) {
        return false;
    }
    while (n != 0) {
        if (m % 7 == 0 || n % 10 == 7) {
            return true;
        }
        n /= 10;
    }
    return 0;
}
int main() {
    int a, sum = 0;
    cin >> a;
    for (int i = 0; i <= a; i++) {
        if (isseven(i) == false) {
            sum += i * i;
        }
    }
    printf("%d\n", sum);
}

image-20240421210501696

更好的解法
#include <stdio.h>
#include <math.h>
int main()
{
    int n,sum=0;
    scanf("%d",&n);
    for(int i=0;i<=n;i++)
        if((i%7)&&i%10!=7&&i/10!=7)
            sum+=pow(i,2);
    printf("%d\n",sum);
    return 0;
}

二、百鸡问题

题目

image-20240421214037033

image-20240421214049331

我的解法
#include<iostream>
using namespace std;
int main(){
	float n=0;
	cin>>n;
	for(int i=0;i<=100;i++){
		for(int j=0;j<=100;j++){
			for(int k=0;k<=100;k++){
				float sum=i*15+9*j+k;//为了解决小数的问题,这样写代码 
				if(sum<=3*n&&i+j+k==100){
					printf("x=%d,y=%d,z=%d\n",i,j,k);
				}
			}
		}
	}
} 

image-20240421214056676

三、Old Bill

题目

image-20240422091536886

image-20240422091628504

解法
//在祖父的文件中发现了一张帐单。72只火鸡$_679_显然代表这些火鸡总价的数字的第一位和最后一位在这里被空白(表示为_)取代,
//因为它们褪色且难以辨认。两个褪色的数字是多少?一只火鸡的价格是多少?
//我们想编写一个程序来解决上述问题的一般版本。N只火鸡$_XYZ_火鸡的总数N在1到99只之间,包括两者。
//总价最初由五位数组成,但我们只能看到在中间的三位数。我们假设第一个数字是非零的,
//一只火鸡的价格是整数美元,所有火鸡的价格都是相同的。给定N、X、Y和Z,编写一个程序来猜测两个褪色的数字和原始价格。
//如果原始价格有多个候选者,则输出应该是最昂贵的一个。 
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
    int n, x, y, z;//n火鸡数、xyz原价格中间三位
    while(~scanf("%d", &n)){
//scanf()是有返回值的,如果遇到错误或遇到end of file,返回值为EOF,EOF值一般在宏定义中为-1,-1二进制取反即为0(假),可用于结束循环
        scanf("%d %d %d", &x, &y, &z);
        int tot, f = 0;//tot原价格、f标记是否存在能够整除火鸡数n的价格
        //这里选择从9枚举到1是为了第一次输出就是最高价格
        for(int a = 9; a >= 1; a--){//a控制原价格的万位[1,9]
            for(int b = 9; b >= 0; b--){//b控制原价格的个位[0,9]
                tot = a * 10000 + x * 1000 + y * 100 + z * 10 + b;
                if(tot % n == 0){//如果原价格tot能够整除火鸡数n
                    f = 1;//则将整除标记置1
                    printf("%d %d %d\n", a, b, tot / n);
                    break;
                }          
            }
            if(f) break;//如果已经整除,则跳出枚举
        }
        if(!f) printf("0\n");//如果没有可以整除的价格,则打印0
    }
    return 0;
}

image-20240422091613212

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值