蓝桥杯学习心得 —— 全排列

题目

如下算式:

A + \frac{B}{C} + \frac{DEF}{GHI} = 10

这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。

比如:

6+8/3+952/714 就是一种解法,

5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?


思路

在解决这个问题之前,我们先思考,如果有1,2,3这三个数,要用编程如何寻找它们所有的排列方式?

其实很简单,可以使用递归的思想,将第i个数放在最开头,然后将其固定,去寻找剩余数组的组合的可能性。

如,默认顺序是[1,2,3],刚开始时将第一个数放在最开头,由于第一个数本来就处于首位,所以交换后仍未[1,2,3],然后只看剩下的数组,[2,3],和上面的一样,交换后仍未[2,3],最后处理[3],这样就得到了[1,2,3]这个组合;

然后依据递归的思想进行回溯,到[2,3],由于第一次取的是2,向下进行的话,就要取3,即将3放在首位,得到了[3,2],这样就得到了[1,3,2]这个排列;

由于[2,3]数组的两个组合都寻找完了,所以向上回溯,到[1,2,3],此时将2放在首位,得到了[2,1,3],然后按相同的方法,去寻找所有的组合。

C语言代码如下:

//寻找[1,2,3]的所有排列
#include
#define N 3

int a[N] = { 1, 2, 3 };			//定义一个全局数组方便访问

void disp() {					//用于显示一种排列的可能性
	for (int i = 0; i < N; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
}

void swap(int *a,int b) {
	int tmp = a[0];
	a[0] = a[b];
	a[b] = tmp;
}
void permt(int *a,int n) {
	if (n == 1) {				//n=1时,说明已经查找到只剩一个数了
		disp();
		return;
	}
	for (int i = 0; i < n; i++) {
		swap(a, i);				//交换第i个到首位
		permt(a + 1, n - 1);	//递归寻找后面的
		swap(a, i);				//交换回来,以免遗漏别的情况
	}
}

int main() {
	permt(a, N);				//第一个参数为传入的数组,第二个为数组长度
}

结果如下 :

1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
3 1 2

有了上面基础后,观察题目,发现这个问题也只不过是1到9这九个数字的排列组合,只不过是添加了一个让它们的组合满足某种运算而已。

由此可以修改上面的代码,简单地写出一下代码来解决:

#include
#define N 9

int a[N] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };	//定义一个全局数组方便访问
int num = 0;								//用于记录解法的个数

void swap(int* a, int b) {
	int tmp = a[0];
	a[0] = a[b];
	a[b] = tmp;
}

void judge() {								//判断是否满足条件
	int b = a[3] * 100 + a[4] * 10 + a[5];
	int c = a[6] * 100 + a[7] * 10 + a[8];
	if (a[0]*a[2]*c+a[1]*c+b*a[2]==10*c*a[2])
		num++;
	return;
}

void permt(int* a, int n) {
	if (n == 1) {						
		judge();							//添加一个判断条件
		return;
	}
	for (int i = 0; i < n; i++) {
		swap(a, i);							//交换第i个到首位
		permt(a + 1, n - 1);				//递归寻找后面的
		swap(a, i);							//交换回来,以免遗漏别的情况
	}
}

int main() {
	permt(a, N);							//第一个参数为传入的数组,第二个为数组长度
	printf("%d", num);
}

得出答案为29.

你可能感兴趣的:(蓝桥杯,学习,c语言)