目录
算法详述
枚举:即对可能的解集合一一列举。
枚举算法的实现往往通过使用循环(嵌套)就能够轻易实现,所以并没有什么思维难度。
解题思路:
1. 对解的每个参数的数据范围采用循环语句一一枚举,对每次枚举采用if语句判断是否是解以及是否是最优解。
枚举小技巧:
1. 有时候,我们枚举的东西如果满足一个公式,我们的循环可以少写一层,优化效率。比如如果枚举A+B+C=100,我们只需要枚举A和B,C可以直接用100-A-B,这样就少一层循环。
2. 当然,改变枚举的顺序也是一种小技巧。一般都是从小到大或者从大到小,但是还有其他顺序,这就用到了贪心算法。
3. 有时候我们需要枚举的是每个东西的状态(一般为两种状态),我们可以用二进制里面的0/1来表示这两种状态来进行枚举。比如(二进制枚举)有5个小朋友,枚举他们是否看过该博客,这时候可以把看过或者没有看过表示两种状态,分别用0和1表示。现在给数字5,二进制是101,说明第1和第3个小朋友看过。所以我们可以枚举0~(31)来表示5个小朋友每个小朋友之间的状态是什么。
4. 有时候,我们枚举的故率达不到题目所需,我们就可以将枚举出来的所有结果事先保存下来,然后在第二份程序里直接调用,这就是打表的思想。
5. 还有时候,简单的循环嵌套可能满足不了我们的需求,可以考虑递归算法实观。
例题
A - 火柴棒等式
给你 nn 根火柴棍,你可以拼出多少个形如 "A+B=C" 的等式?等式中的 A、B、C 是用火柴棍拼出的整数(若该数非零,则最高位不能是 0)。
用火柴棍拼数字 0-9,0−9 的拼法如图所示
注意:
加号与等号各自需要两根火柴棍
如果 A B,则A+B=C与B+A=C 视为不同的等式(A、B、C ≥0)
n 根火柴棍必须全部用上
输入格式
输入一个整数 n(n≤24)。
输出格式
输出能拼成的不同等式的数目。
Sample Input
5
Sample Output
0
分析:
(1)0~9所需要的火柴数:6,2,5,5,4,5,6,3,7,6 根火柴
(2)因为+=一共是4根,所以最后火柴数需要加上4
(3)因为1是所有数字中所用火柴数最少的数字,1111是四位数中最大的数,而且1111+1=1112此时一共25根>24,所以基本上不会到达四位数,因此最后循环到1000即可。由于担心某种特殊情况没有考虑到,可以将a数组放大到2000
(4)首先需要一个数组存放0~2000苏需要的火柴数,即数组a。然后求a[i]+a[j]+a[i+j]+4的火柴数,如果该数=n则让s加1并且继续循环,直到全部循环完成即可。
(5)其中11111问题的解析:关于《啊哈!算法》第三章火柴棍等式“1111”问题的解析_BDICOMENOW的博客-CSDN博客
代码 :
#include<iostream>
using namespace std;
int main()
{
int a[2001] = { 6 }, n, c[10] = { 6,2,5,5,4,5,6,3,7,6 }, s = 0, i, j;
//a数组表示下标所需要的火柴数,a[0]=6,其他的是0;n即输入的n的大小;其中c数组存储0~9数字所需要的火柴数
cin >> n;
for (i = 1; i <= 2000; i++)//因为1111是四位数用的最少的数,1111+1=1112此时就25根棍子了,所以基本上就不会实现四位数,但是把上界稍微放大了
{
j = i;
while (j >= 1)//将数字进行十进制的拆分,将i所需要的火柴数放入a数组中
{
a[i] = a[i] + c[j % 10];
j = j / 10;
}
}
for (i = 0; i <= 1000; i++)//求出该等式所需要的火柴棍
{
for (j = 0; j <= 1000; j++)
if (a[i] + a[j] + a[i + j] + 4 == n)//+4是因为+和=一共需要四根火柴棍
s++;//s表示符合要求的答案数
}
cout << s;
return 0;
}
B - 砝码称重
设有 1g,2g,3g,5g,10g,20g的砝码各若干枚(其总重小于等于 1000),现在求问这些砝码能称出多少不同的重量。
输入格式
一行六个整数,分别代表 1g 砝码的个数,分别代表 2g砝码的个数,分别代表 3g 砝码的个数,分别代表 5g 砝码的个数,分别代表 10g 砝码的个数,分别代表 20g 砝码的个数。
输出格式
输出一行,格式为
Total=
n。(n 表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况)
Sample Input
1 1 0 0 0 0
Sample Output
Total=3
分析:
此题最好是可以用到枚举小技巧3,具体代码可见:(42条消息) B - 砝码称重_bairimeng16的博客-CSDN博客
代码:
#include <iostream>
using namespace std;
int main() {
int h[1005] = { 0 }, cm[7]; // 9018最奇怪的一点,重量必须是1004以下,否则会WA
for (int i = 1; i <= 6; i++) cin >> cm[i];
for (int a = 0; a <= cm[1]; a++) // 枚举个数
for (int b = 0; b <= cm[2]; b++)
for (int c = 0; c <= cm[3]; c++)
for (int d = 0; d <= cm[4]; d++)
for (int e = 0; e <= cm[5]; e++)
for (int f = 0; f <= cm[6]; f++) {
h[a + 2 * b + 3 * c + 5 * d + 10 * e + 20 * f] = 1; // 重量桶
}
int sum = 0;
for (int i = 1; i <= 1004; i++) if (h[i]) sum++;
cout << "Total=" << sum << endl;
return 0;
}