zoukankan      html  css  js  c++  java
  • 算法与数据结构---2、枚举

    算法与数据结构---2、枚举

    一、总结

    一句话总结:

    枚举法又称穷举法,它是根据题意,枚举所有可能状态,并用问题给定的条件来约束状态,检验哪些是需要的,哪些是不需要的。

    1、枚举法的代码结构?

    循环+判断语句,枚举几个变量就循环几次
    设ai1—状态元素ai的最小值;aik—状态元素ai的最大值(1≤i≤n),即a11≤a1≤a1k,a21≤a2≤a2k, ai1≤ai≤aik,
    ……,an1≤an≤ank
    for(a1=a11;a1<=a1k;a1++)
         for(a2=a21;a2<=a2k;a2++)
          .....
             for(ai=ai1;ai<=aik;ai++)
                 .....
                    for(an=an1;an<=ank;an++)
                           if(状态(a1,...,ai...,an)满足检验条件)
                                            输出问题的解;

    2、枚举算法的常用优化?

    a、缩小枚举范围
    b、减少枚举变量
    c、使用其它算法

    3、枚举法敲代码技巧?

    弄清楚枚举变量、枚举范围、枚举判断条件,敲代码就非常简单,而且不容易出错了

    枚举变量:
    枚举范围:
    枚举判断条件:

     1 /*
     2 
     3 枚举变量:公鸡
     4 枚举范围:公鸡1-14,总计算次数14
     5 枚举判断条件:
     6 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
     7 小鸡%3==0
     8 (100-7x)%4==0
     9 
    10 
    11 */
    12 #include <stdio.h>
    13 int main()
    14 {
    15     for (int i = 1; i <= 14; i++)
    16     {
    17         if ((100 - 7 * i) % 4 == 0)
    18         {
    19             int y = (100 - 7 * i) / 4;
    20             int z = 100 - i - y;
    21             if (5 * i + 3 * y + z / 3 == 100 && z % 3 == 0)
    22             {
    23                 printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只
    ", i, y, z);
    24             }
    25         }
    26     }
    27 
    28     return 0;
    29 }

    二、枚举

    博客对应课程的视频位置:2、枚举
    https://www.fanrenyi.com/video/27/252

    一、枚举法的基本思想

    枚举法又称穷举法,它是根据题意,枚举所有可能状态,并用问题给定的条件来约束状态,
    检验哪些是需要的,哪些是不需要的。

    枚举结构:循环+判断语句。



    二、枚举法的框架结构

    设ai1—状态元素ai的最小值;aik—状态元素ai的最大值(1≤i≤n),即a11≤a1≤a1k,a21≤a2≤a2k, ai1≤ai≤aik,
    ……,an1≤an≤ank
    for(a1=a11;a1<=a1k;a1++)
         for(a2=a21;a2<=a2k;a2++)
          .....
             for(ai=ai1;ai<=aik;ai++)
                 .....
                    for(an=an1;an<=ank;an++)
                           if(状态(a1,...,ai...,an)满足检验条件)
                                            输出问题的解;


    三、枚举法的优缺点

    用枚举法解题的最大的缺点是运算量比较大,解题效率不高,如果枚举范围太大(一般以不超过两百万次为限),在时间上就难以承受。

    但枚举算法的思路简单,程序编写和调试方便,比赛时也容易想到,在比赛中,时间是有限的,我们比赛的最终目标是求出问题解,
    因此,如果题目的规模不是很大,在规定的时间与空间限制内能够求出解,那么最好是采用枚举法。


    四、枚举算法的优化

    a、缩小枚举范围
    b、减少枚举变量
    c、使用其它算法

    五、枚举法敲代码技巧(注意)

    弄清楚枚举变量、枚举范围、枚举判断条件,敲代码就非常简单,而且不容易出错了

    枚举变量:
    枚举范围:
    枚举判断条件:

    三、百钱买百鸡问题及优化

    博客对应课程的视频位置:2、枚举
    https://www.fanrenyi.com/video/27/252

    1、问题

    百钱买百鸡
    公鸡一只五块钱,母鸡一只三块钱,小鸡一块钱三只,
    现在要用一百块钱买一百只鸡,每种鸡最少一只,问公鸡、母鸡、小鸡各多少只?

    2、分析及代码实现

    枚举变量:公鸡、母鸡、小鸡
    枚举范围:公鸡、母鸡、小鸡都是1-100次,总计算次数100*100*100
    枚举判断条件:
    钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    总鸡数=100:公鸡+母鸡+小鸡 = 100
    小鸡%3==0

     1 /*
     2 
     3 百钱买百鸡
     4 公鸡一只五块钱,母鸡一只三块钱,小鸡一块钱三只,
     5 现在要用一百块钱买一百只鸡,每种鸡最少一只,问公鸡、母鸡、小鸡各多少只?
     6 
     7 
     8 枚举变量:公鸡、母鸡、小鸡
     9 枚举范围:公鸡、母鸡、小鸡都是1-100次,总计算次数100*100*100
    10 枚举判断条件:
    11 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    12 总鸡数=100:公鸡+母鸡+小鸡 = 100
    13 小鸡%3==0
    14 
    15 */
    16 
    17 #include <stdio.h>
    18 int main()
    19 {
    20     for (int i = 1; i <= 100; i++)
    21         for (int j = 1; j <= 100; j++)
    22             for (int k = 1; k <= 100; k++)
    23             {
    24                 if (5 * i + 3 * j + k / 3 == 100 && k % 3 == 0 && i + j + k == 100)
    25                 {
    26                     printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只
    ", i, j, k);
    27                 }
    28             }
    29     return 0;
    30 }

    3、优化一:缩小枚举范围

    百钱百鸡问题优化一:

    5公鸡+3母鸡+1/3小鸡 = 100
    公鸡+母鸡+小鸡 = 100

    缩小枚举范围

    枚举变量:公鸡、母鸡、小鸡
    枚举范围:公鸡1-18,母鸡1-32 ,小鸡1-98次,总计算次数18*32*98
    枚举判断条件:
    钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    总鸡数=100:公鸡+母鸡+小鸡 = 100
    小鸡%3==0

     1 /*
     2 
     3 百钱百鸡问题优化一:
     4 
     5 5公鸡+3母鸡+1/3小鸡 = 100
     6 公鸡+母鸡+小鸡 = 100
     7 
     8 缩小枚举范围
     9 
    10 枚举变量:公鸡、母鸡、小鸡
    11 枚举范围:公鸡1-18,母鸡1-32 ,小鸡1-98次,总计算次数18*32*98
    12 枚举判断条件:
    13 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    14 总鸡数=100:公鸡+母鸡+小鸡 = 100
    15 小鸡%3==0
    16 
    17 
    18 */
    19 
    20 #include <stdio.h>
    21 int main()
    22 {
    23     for (int i = 1; i <= 18; i++)
    24         for (int j = 1; j <= 32; j++)
    25             for (int k = 1; k <= 98; k++)
    26             {
    27                 if (5 * i + 3 * j + k / 3 == 100 && k % 3 == 0 && i + j + k == 100)
    28                 {
    29                     printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只
    ", i, j, k);
    30                 }
    31             }
    32     return 0;
    33 }

    4、优化二:减少枚举变量

     1 /*
     2 
     3 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
     4 总鸡数=100:公鸡+母鸡+小鸡 = 100
     5 
     6 设公鸡 x 只,母鸡 y 只,小鸡 z 只
     7 
     8 5x+3y+1/3z = 100
     9 x+y+z = 100
    10 
    11 枚举了x和y之后,z的值是固定的,z=100-x-y
    12 所以这个时候,z就不用枚举了
    13 
    14 枚举变量:公鸡,母鸡
    15 枚举范围:公鸡1-18,母鸡1-32,总计算次数 18*32
    16 枚举判断条件:
    17 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    18 小鸡%3==0
    19 
    20 优化:减少了枚举的变量
    21 减少枚举的变量之后,枚举的次数大幅减少
    22 
    23 */
    24 #include <stdio.h>
    25 int main()
    26 {
    27     for (int i = 1; i <= 18; i++)
    28         for (int j = 1; j <= 32; j++)
    29         {
    30             int z = 100 - i - j;
    31             if (5 * i + 3 * j + z / 3 == 100 && z % 3 == 0)
    32             {
    33                 printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只
    ", i, j, z);
    34             }
    35         }
    36 
    37     return 0;
    38 }

    5、优化三:根据题目关系,进一步减少枚举变量

     1 /*
     2 
     3 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
     4 总鸡数=100:公鸡+母鸡+小鸡 = 100
     5 
     6 设公鸡 x 只,母鸡 y 只,小鸡 z 只
     7 
     8 5x+3y+1/3z = 100
     9 x+y+z = 100
    10 
    11 第一个式子*3
    12 15x+9y+z = 300
    13 x+y+z = 100
    14 
    15 得:
    16 14x+8y=200
    17 18 7x+4y=100
    19 y=(100-7x)/4
    20 z=100-x-(100-7x)/4
    21 
    22 根据这个式子,有x之后,我们就可以得到y,从而得到z
    23 这里7x小于等于96,x取值为1-14
    24 
    25 枚举变量:公鸡
    26 枚举范围:公鸡1-14,总计算次数14
    27 枚举判断条件:
    28 钱数=100:5公鸡+3母鸡+1/3小鸡 = 100
    29 小鸡%3==0
    30 (100-7x)%4==0
    31 
    32 
    33 */
    34 #include <stdio.h>
    35 int main()
    36 {
    37     for (int i = 1; i <= 14; i++)
    38     {
    39         if ((100 - 7 * i) % 4 == 0)
    40         {
    41             int y = (100 - 7 * i) / 4;
    42             int z = 100 - i - y;
    43             if (5 * i + 3 * y + z / 3 == 100 && z % 3 == 0)
    44             {
    45                 printf("公鸡 %2d 只,母鸡 %2d 只,小鸡 %2d 只
    ", i, y, z);
    46             }
    47         }
    48     }
    49 
    50     return 0;
    51 }

  • 相关阅读:
    Redis批量删除key的小技巧,你知道吗?
    Spring条件注解@Conditional
    Spring Boot 2.X 如何快速集成单元测试?
    idea git提交时候提示 --author 'java_suisui' is not 'Name ' and matches no existing author
    Spring Boot 2.X 如何添加拦截器?
    SpringMVC+Mybatis 如何配置多个数据源并切换?
    Spring Boot 2.X 如何优雅的解决跨域问题?
    基于SSL实现MySQL的加密主从复制
    mysql -- mysql基于ssl的主从复制
    MySQL DB 主从复制之SSL
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/12986089.html
Copyright © 2011-2022 走看看