一.穷举/枚举
根据问题的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到将全部情况验证完毕。
若某个情况验证符合题目的全部条件,则为本问题的一个解;
若全部情况验证后都不符合题目的全部条件,则问题无解。
二.找出100~200间的全部素数
#include <stdio.h>
#include <math.h>
int main()
{
int i, m, n=0, is_prime;
for (m = 101; m <= 200; m += 2)
{
is_prime = 1;//1为素数,0不是;
for (i = 2; i <= sqrt(m); ++i)//技巧:利用sqrt(m)因子对称性,降低循环次数;
{
if (m % i == 0)
{
is_prime = 0;
break;
}
}
if (is_prime == 1)
{
printf("%d\t", m);
++n;//++n效率一般稍高于n++;
if (n % 5 == 0) printf("\n");//技巧:每输出5次换行一次;
}
}
}
三.穷举法求解:百鸡百钱
问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问
鸡翁、鸡母、鸡雏各几何?
分析:设鸡翁、母、雏分别为x,y,z,有 x+y+z=100;买百鸡要百钱,有 5x+3y+z/3=100
x、y、z取值范围 x: 0~20;y: 0~33; z: 0~100
解法一: 常规穷举方法
#include <stdio.h>
int main()
{
int x, y, z;
for (x = 0; x <= 20; ++x)//穷举中...
{
for (y = 0; y <= 33; ++y)
{
for (z = 0; z <= 100; ++z)
{
if (x + y + z == 100 && 5*x + 3*y + z / 3 == 100 && z % 3 == 0)
{
printf("鸡翁%2d只,鸡母%2d只,鸡雏%2d只\n", x, y, z);
}
}
}
}
}
解法二: 考虑效率,降循环次数
#include <stdio.h>
int main()
{
int x, y, z;
for (x = 0; x <= 20; ++x)
{
for (y = 0; y <= 33; ++y)
{
z = 100 - x - y;//x,y确定,z就确定,所以不用穷举列出,循环次数降低100倍;
if (5 * x + 3 * y + z / 3 == 100 && z % 3 == 0)
{
printf("鸡翁%2d只,鸡母%2d只,鸡雏%2d只\n", x, y, z);
}
}
}
}
四.穷举再例: 如何派任务
问题:某侦察队接到一项紧急任务,要求在A、
B、C、D、E、F六个队员挑若干人,但有以
下限制条件:
① A和B两人中至少去一人
② A和D不能一起去
③ A、E和F中要派两人去
④ B和C都去或都不去
⑤ C和D两人中去一个
⑥ 若D不去,则E也不去
分析:用a、b、c、d、e、f的值分别表示对六个人的选择结果,值为1表示该去;值为0表示不该去;
①a+b>=1;
②(a+d)!=2;(或a+d<=1)
③a+e+f=2;
④b+c =2或b+c = 0;
⑤c+d =1;
⑥d+e=0或d=1;
#include <stdio.h>
int main()
{
int a, b, c, d, e, f;
for (a = 0; a <= 1; a++)
for (b = 0; b <= 1; b++)
for (c = 0; c <= 1; c++)
for (d = 0; d <= 1; d++)
for (e = 0; e <= 1; e++)
for (f = 0; f <= 1; f++)
{
if (a + b >= 1 && a + d != 2
&& a + e + f == 2 && (b + c == 2 || b + c == 0)
&& c + d == 1 && (d + e == 0 || d == 1))
printf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d\n",
a, b, c, d, e, f);
}
}
运行结果:
a=1,b=1,c=1,d=0,e=0,f=1
实践项目
【项目1-小明借书】
小明有五本新书,要借给A,B,C三位小朋友,若每人每次只能借一本,则可以有多少种不同的借法?
#include <stdio.h>
int main()
{
int a, b, c, i = 0;
for (a = 1; a <= 5; a++)
for (b = 1; b <= 5; b++)
for (c = 1; c <= 5; c++)
{
if (a != b && b != c && c != a)
++i;
}
printf("%d\n", i);
}
运行结果:60
【项目2-水仙花数】
对于三位数字,若各位数字立方和等于该数,该数就是水仙花数。如153:153=13+53+33
#include <stdio.h>
int main()
{
int a, b, c, x = 0;
for (a = 1; a <= 9; a++)
for (b = 0; b <= 9; b++)
for (c = 0; c <= 9; c++)
{
x = 100 * a + 10 * b + c;
if (x==a * a * a + b * b * b + c * c * c)
printf("%d\n", x);
}
}
【项目3-鸡兔共笼】
鸡兔共有30只,脚共有90只,问鸡兔各有多少?
#include <stdio.h>
int main()
{
int x, y;//兔x,鸡y;
for (x = 0; x <= 22; x++)
{
y = 30 - x;
if (4 * x + 2 * y == 90)
{
printf("兔%d只,鸡%d只\n", x, y);
}
}
}
【项目4-换分币】
用一元人民币兑换成1分、2分和5分硬币,有多少种不同的兑换方法?请输出所有可能的方案。
提示:根据题意设i,j,k分别为兑换的1分、2分、5分硬币的枚数,则i,j,k的值应满足:i+j2+k5=100,根据取值范围构造循环解题即可。
#include <stdio.h>
int main()
{
int i, j, k, count = 0;
for (i = 0; i <= 100; i++)
for (j = 0; j <= 50; j++)
for (k = 0; k <= 20; k++)
{
if (i + 2 * j + 5 * k == 100)
{
++count;
printf("第%2d种:1分%2d个,2分%2d个,5分%2d个\n", count, i, j, k);
if (count % 50 == 0)//每输出50个方案暂停一次
{
printf("按任意键继续输出...\n");
getchar();//暂停等待输入
}
}
}
}
【项目5-年龄几何】
张三、李四、王五、刘六的年龄成一等差数列,他们四人的年龄相加是26,相乘是880,求以他们的年龄为前4项的等差数列的前20项。
提示:设数列的首项为n,公差为a,则前4项之和为"4n+6a",前4 项之积为"n*(n+a)(n+a+a)(n+a+a+a)"。同时"1<=a<=4",“1<=n<=6”。可采用穷举法求出此数列
#include <stdio.h>
int main()
{
int n, a;
for (a = 1; a <= 4; ++a)
for (n = 1; n <= 6; n++)
{
if (4 * n + 6 * a == 26 && n * (n + a) * (n + a + a) * (n + a + a + a) == 880)
{
for (int i = 0; i <= 19; ++i)
{
printf("%d\t", n + a * i);
if ((i + 1) % 5 == 0) printf("\n");//每输出5个换行;
}
}
}
}
运行结果:
2 5 8 11 14
17 20 23 26 29
32 35 38 41 44
47 50 53 56 59
【项目6-三色球问题】
若一个口袋中放有12个球,其中有3个红的。3个白的和6个黒的,问从中任取8个共有多少种不同的颜色搭配?
#include <stdio.h>
int main()
{
int a, b, c,count=0;
for (a = 0; a <= 3; a++)
for (b = 0; b <= 3; b++)
{
c = 8 - a - b;
if (c <= 6)
{
++count;
printf("第%d种:红%d,白%d,黑%d\n", count, a, b, c);
}
}
}
运行结果:
第1种:红0,白2,黑6
第2种:红0,白3,黑5
第3种:红1,白1,黑6
第4种:红1,白2,黑5
第5种:红1,白3,黑4
第6种:红2,白0,黑6
第7种:红2,白1,黑5
第8种:红2,白2,黑4
第9种:红2,白3,黑3
第10种:红3,白0,黑5
第11种:红3,白1,黑4
第12种:红3,白2,黑3
第13种:红3,白3,黑2
【项目7-找数字】
(1)求满足下式的 x,y,z
#include <stdio.h>
int main()
{
int x, y, z, i;
for (x = 1; x < 5; x++)
for (y = 1; y < 5; y++)
for (z = 1; z < 7; z++)//z+z=2 =>z=1或6;
{
i = (x * 100 + y * 10 + z) + (100 * y + 10 * z + z);
if (i == 532)
printf("x=%d, y=%d, z=%d\n", x, y, z);
}
}
运行结果:
x=3, y=2, z=1
(2)在下面的加法算式中,不同的符号代表不同的数字,相同的符号代表相同的数字。请设计程序求出"都、要、学、C"4个符号分别代表的数字
#include <stdio.h>
int main()
{
int 都, 要, 学, c;
for (都 = 1; 都 <= 2; 都++)
for (要 = 0; 要 <= 9; 要++)
for (学 = 0; 学 <= 9; 学++)
for (c = 2; c <= 7; c++)
{
if (4 * c + 30 * 学 + 200 * 要 + 1000 * 都 == 2008)
{
if (c != 学 && c != 要 && c != 都 && 学 != 要 && 学 != 都 && 要 != 都)
printf("都:%d,要:%d,学:%d,C:%d\n", 都, 要, 学, c);
}
}
}
运行结果:
都:1,要:4,学:6,C:7
都:1,要:5,学:0,C:2
【项目8-谁是小偷】
警察局抓住了A、B、C、D四名盗窃嫌疑犯,其中只有一人是小偷。在审问时,A说:“我不是小偷”;B说:“C是小偷”;C说:“小偷肯定是D”;D说:“C在冤枉好人”。现在已经知道这四人中有三人说的是真话,一人说的是假话。请问到底谁是小偷?
提示:设4个变量a,b,c,d,为0时表示不是小偷,为1时表示是小偷,用四重循环穷举a,b,c,d可能的取值的组合,对每一种组合判断其是否符合题目中给出的约束。最后结论:C是小偷。
#include <stdio.h>
int main()
{
int a, b, c, d;
for (a = 0; a <= 1; ++a)
for (b = 0; b <= 1; ++b)
for (c = 0; c <= 1; ++c)
for (d = 0; d <= 1; ++d)
{
if ((a == 0) + (c == 1) + (d == 1) + (d == 0) == 3 && a + b + c + d == 1)
//if((!a)+(c)+(d)+(!d)==3 && a+b+c+d==1) //其中!a与a==0等价,c与c==1等价
printf("A:%d, B:%d, C:%d, D:%d\n", a, b, c, d);
}
}
【项目9-污损的单据】
(1)有等式[※×(※3+※)]2=8※※9,其中※处为1个数字,滴上了墨水无法辨认。请编程找出※表示哪个数字。
(2)有等式[※×(※3○※)]2=8※※9,其中※处为1个数字,○处为+、-、×、÷四个运算符之一,现滴上了墨水无法辨认。请编程找出※表示哪个数字,○表示哪个运算符
#include <stdio.h>
int main()
{
int a, b, c, d, e, s;
for (a = 0; a <= 9; a++)
for (b = 0; b <= 9; b++)
for (c = 0; c <= 9; c++)
for (d = 0; d <= 9; d++)
for (e = 0; e <= 9; e++)
{
s = a * (b * 10 + 3 + c);
if (s * s == 8000 + d * 100 + e * 10 + 9)
{
printf("等式为:[%d×(%d3+%d)]^2=8%d%d9\n", a, b, c, d, e); //※×(※3+※)]^2=8※※9
}
}
}
运行结果:
等式为:[1×(93+0)]^2=8649
等式为:[3×(23+8)]^2=8649
#include <stdio.h>
int main()
{
int a, b, c, d, e, s;
for (a = 0; a <= 9; a++)
{
for (b = 0; b <= 9; b++)
{
for (c = 0; c <= 9; c++)
{
for (d = 0; d <= 9; d++)
{
for (e = 0; e <= 9; e++)
{
s = a * (b * 10 + 3 + c);
if (s * s == 8000 + d * 100 + e * 10 + 9)
{
printf("等式为:[%d×(%d3+%d)]^2=8%d%d9\n", a, b, c, d, e);
}
s = a * (b * 10 + 3 - c);
if (s * s == 8000 + d * 100 + e * 10 + 9)
{
printf("等式为:[%d×(%d3-%d)]^2=8%d%d9\n", a, b, c, d, e);
}
s = a * ((b * 10 + 3) * c);
if (s * s == 8000 + d * 100 + e * 10 + 9)
{
printf("等式为:[%d×(%d3*%d)]^2=8%d%d9\n", a, b, c, d, e);
}
if (c != 0)
{
s = a * ((b * 10 + 3) / c);
if (s * s == 8000 + d * 100 + e * 10 + 9)
{
printf("等式为:[%d×(%d3/%d)]^2=8%d%d9\n", a, b, c, d, e);
}
}
}
}
}
}
}
}
运行结果:
等式为:[1×(93+0)]^2=8649
等式为:[1×(93-0)]^2=8649
等式为:[1×(93*1)]^2=8649
等式为:[1×(93/1)]^2=8649
等式为:[3×(23+8)]^2=8649
等式为:[3×(33-2)]^2=8649
等式为:[3×(63/2)]^2=8649
等式为:[3×(93/3)]^2=8649