第40节 穷举法解题

一.穷举/枚举
 根据问题的部分条件确定答案的大致范围,并在此范围内对所有可能的情况逐一验证,直到将全部情况验证完毕。
 若某个情况验证符合题目的全部条件,则为本问题的一个解;
 若全部情况验证后都不符合题目的全部条件,则问题无解。

二.找出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,62:0,3,53:1,1,64:1,2,55:1,3,46:2,0,67:2,1,58:2,2,49:2,3,310:3,0,511:3,1,412:3,2,313: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

猜你喜欢

转载自blog.csdn.net/m0_51439429/article/details/115417584
今日推荐