微信扫一扫打赏支持

算法与数据结构---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 只\n", 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 只\n", 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 只\n", 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 只\n", 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 只\n", i, y, z);
46             }
47         }
48     }
49 
50     return 0;
51 }

 

 

 

 

 

posted @ 2020-05-29 11:54  范仁义  阅读(677)  评论(0编辑  收藏  举报