算法(二)暴力枚举

一、概述

1、概念

枚举,顾名思义,就是将所有情况都举出,并判断其是否符合题目条件。所以枚举的基本方法便是分析题意后,找到一个合适的维度列举每一个元素,以完成题目。其中如何找到一个合适的维度来进行枚举便是其中的最大难点

2、枚举的基本条件

(1)时间条件

枚举范围小或时间无限制(蓝桥杯填空题)

一般来说主流的OJ当中,1000ms的时间限制下可以运行操作数为107以内的运算(通常106以内较为保险),所以在采用枚举方法之前最好看一下数据范围,确保整个程序的执行操作数不会超过106-107这个量级,如果超过了就尝试更换枚举的维度或者使用其他算法吧。

(2)编程上的实现条件

在编程实现上,一般来说暴力枚举需要两个条件,一是枚举的范围一般需要连续,如果枚举范围是离散的,那么一般很难使用for循环枚举出所有状态,也就不能保证解的完整性(不过有些时候数据看似离散,但实际上可以经过处理变得连续,如构造数组)。第二个条件是枚举内容需要已知,不能在枚举到某个地方的时候出现未知(不过这个一般都被满足)。

3、不适用的情况

(1)简单的暴力枚举一般只适用于解决简单的问题

(2)难以求出或范围特别大,明显超时(数论等)

https://www.luogu.com.cn/problem/P1403

4、解题思路

(1)找到枚举变量**(尽量由已知推未知)**

(2)找到并尽量缩小范围(根据题意但无需太过精确,可以过大,条件在if中判断即可

(3)依据题意进行操作**(尽量剪枝)**

二、数学运算问题

技巧

(1)枚举变量

按位数0-9(一),按数字(二),或离散时构造数组(一、2)

尽量由已知推未知:一般有一个变量可以直接运算得出。尽量用乘法(二、1)

(2)常见限制

位数、位数字出现次数

(3)取位方法

//取b由低到高位
for(int i = 0;b != 0;i++)
{
    a[i] = b % 10;
    b /= 10;
}

(4)记录位数字出现个数

使用数组a[10],a[i]代表数字i出现了a[i]次

(5)从小到大

从小到大枚举(一、4)

(一)按位枚举

适用于条件偏向于位

1、4个不同的数字

org[i]代表org[i]已出现

https://blog.csdn.net/weixin_38172774/article/details/87354310

2、数码管的标价

https://blog.csdn.net/weixin_38172774/article/details/87354310

思路:先找一个,然后继续找另一个

枚举变量:离散可构造数组

3、对着数字发呆

https://blog.csdn.net/weixin_38172774/article/details/87354310

4、四平方和定理

https://blog.csdn.net/weixin_38172774/article/details/87354310

从小到大:从小到大枚举

#include <iostream>
#include <math.h>

using namespace std;

int main() {
    int n,temp;
    int a,b,c;
    //注意类型!
    double d;

    cin >> n ;

    for(a = 0 ; a*a <= n; a++){
        for(b = a ; b*b <= n; b++){
            for(c = b ; c*c <= n; c++){
                d = sqrt(n-a*a-b*b-c*c);
                //判断d是否为整数!
                if(d == int(d)){
                    cout << a<<" "<<b<<" "<<c<<" "<<d;
                    //输出第一个表示法!
                    return 0;
                }
            }
        }
    }
}


5、请猜谜

https://blog.csdn.net/weixin_38172774/article/details/87354310

注意判断是否为6位数

(二)数字枚举

适用于数字x,y或数字并非刚好为临界(如1111)

1、abcde/fghij=n

https://blog.csdn.net/weixin_38172774/article/details/87354310

b/a = n得b = a * n;避免小数的出现,自然就节约判断了

可以确定:a来说最小为01234,最大为98765

2、火柴棒等式

由于题目中已经给出,最多有24根火柴,而等号和加号各用4根的前提下,A\B\C三个数则总共只有20根火柴,数据范围较小,可以用枚举法枚举A、B。这个时候我们发现,0-9这10个数字所用的火柴数为:6,2,5,5,4,5,6,3,7,6,很明显数字1用的火柴棒最少只要2根,不妨让B为1,那么A和C最多可以使用18根火柴,而C>=A,满足条件的A的最大取值为1111。所以枚举A和B的范围是从0~1111。(应该是过大了)

#include <stdio.h>
#include <stdlib.h>
int a[2223]= {6,2,5,5,4,5,6,3,7,6};//前10需要的火柴数目
const int b[10]= {6,2,5,5,4,5,6,3,7,6};//定义b数组的值,不可改变
int need(int n)
{
    int t, num;
    num=0;
    if(n==0) return 6;
    while(n>0)
    {
        t=n%10;
        num+=b[t];//统计数字并且把这些数字所需要的火柴数目加起来
        n/=10;//跳过最后一个数字
    }
    return num;
}
int main( )
{
    int n,i,j,A,B,C,D,sum;
    scanf("%d",&n);
    sum=0;
    //预处理
    for(i=10; i<2223; i++)
        a[i]=need(i);//把每个数字需要的火柴数目赋值
    for(i=0; i<=1111; i++)
    {
        for(j=0; j<=1111; j++)
        {
            A=a[i];//A的火柴数目
            B=a[j];//B的火柴数目
            C=n-4-A-B;//C的火柴数目
            D=a[i+j];//等式的实现是通过i+j=(i+j)
            if(D==C) sum++;//如果符合等式
        }
    }
    printf("%d\n",sum);
    return 0;
}
 

3、uva10976

y的范围为 k<y<2k

注意判断x是否为整数 k*y%(y-k)) == 0

https://www.cnblogs.com/rhythmic/p/5980017.html

三、模拟+暴力枚举

技巧

依据题意即可

1、机器人繁殖

https://blog.csdn.net/weixin_38172774/article/details/87354310

#include <iostream>

using namespace std;

int main() {
    int n;
    long long total,count = 0,thisYear=0,lastYear=0 ;
    cin >> n >>total;
    //暴力枚举可能的最初值
    for (int i = 1; i < total; ++i) {
        count = i; thisYear = i;
        for (int j = 0; j < n; ++j) {
            lastYear = thisYear;
            thisYear = lastYear*2-1;
            count+= thisYear;
        }
        if (count == total) {
            cout << i;
            return 0;
        } else continue;
    }
}

2、HDU1422 重温世界杯

http://acm.hdu.edu.cn/showproblem.php?pid=1422

https://www.cnblogs.com/rhythmic/p/5980017.html

哪里用到那个结论了?

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 200000 + 5;
int a[maxn];
int main()
{
     int n;
     while(scanf("%d",&n) != EOF)
     {
            //存净收入
            for(int i = 1;i <= n;i++)
            {
                  int x , y;
                  scanf("%d%d",&x,&y);
                  a[i] = x - y;
                  //拓展数组以便模拟循环!
                  a[n+i] = x - y;
            }
            int num = 0;
            int Max = 0;
            //现在的钱
            int ans = 0;
             //遍历整个数组!
             for(int i = 1;i <= 2*n;i++)
             {
                 ans += a[i];
                 if(ans >= 0)
                      num++;
                 else
                 {
                       num = 0 , ans = 0;
                 }
                 Max = max(num , Max);
                 if(Max == n) break;
             }

             printf("%d\n",Max);
     }
}

3、滑雪课程设计

对最矮进行枚举

https://www.luogu.com.cn/problem/P3650

  • 29
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
仅仅是作为搬运工。 算法精粹——举一反三,抛弃题海战术 本书的目标读者是准备去硅谷找工作的码农,也适用于在国内找工作的码农,以及刚接触ACM算法竞赛的新手。 市场上讲解算法的书已经汗牛充栋,为什么还要写这本书呢?主要原因是我对目前市场上的大部分算法书都不太满意。 本书有如下特色: 背后有强大的AlgoHub支持。 本书的所有题目,都可以在 www.algohub.org(即将上线) 上在线判断代码。这样的一大好处是,读者可以边看书,边实现自己的代码,然后提交到网站上验证自己的想法是否正确。AlgoHub的使命是成为最好的算法学习和交流平台。AlgoHub囊括了 POJ, ZOJ, leetcode, HackerRank 等网站的经典题目(一些质量不高的题目则忽略),且 AlgoHub有非常简单的加题系统,用户不需要写一行代码即可自己添加题目,所以AlgoHub的题库还在飞速增长中。 每道题都有完整的代码。 市场上的大部分书,都会讲思路,但给出的代码都是片段,不是完整可编译的代码。本书每题都有完整的代码,且每个代码经过千锤百炼,保证可读性的前提下尽可能简短,方面读者在面试中能快速写出来。 每道题都有多种解法。 本书的宗旨是,用尽可能少的题目,覆盖尽可能多的算法。本书中的的每道题都有多种解法,每种解法不是简单的小改进,而是完全不同的思路,力求举一反三,让读者触类旁通。 本书支持多种主流编程语言。 目前支持 Java, C++, C#, Python, Ruby, JavaScript, Swift, Scala, Clojure, 将来还会支持更多编程语言。 在线阅读 https://www.gitbook.com/book/soulmachine/algorithm-essentials/ 内容目录 介绍 线性表 数组 Remove Duplicates from Sorted Array Remove Duplicates from Sorted Array II Longest Consecutive Sequence Two Sum 3Sum 3Sum Closest 4Sum Remove Element Move Zeroes Next Permutation Permutation Sequence Valid Sudoku Trapping Rain Water Rotate Image Plus One Climbing Stairs Set Matrix Zeroes Gas Station Candy Majority Element Rotate Array Contains Duplicate Contains Duplicate II Contains Duplicate III Product of Array Except Self Game of Life Increasing Triplet Subsequence 单链表 Reverse Linked List Odd Even Linked List Add Two Numbers Reverse Linked List II Partition List Remove Duplicates from Sorted List Remove Duplicates from Sorted List II Rotate List Remove Nth Node From End of List Swap Nodes in Pairs Reverse Nodes in k-Group Copy List with Random Pointer Linked List Cycle Linked List Cycle II Reorder List LRU Cache Palindrome Linked List 字符串 Valid Palindrome Implement strStr() String to Integer (atoi) Add Binary Longest Palindromic Substring Regular Expression Matching Wildcard Matching Longest Common Prefix Valid Number Integer to Roman Roman to Integer Count and Say Anagrams Valid Anagram Simplify Path Length of Last Word Isomorphic Strings Word Pattern 栈和队列 栈 Min Stack Valid Parentheses L

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值