文章参考:
http://blog.csdn.net/liuchuo/article/details/51994221
http://blog.csdn.net/liu940204/article/details/51005414
http://blog.csdn.net/liu940204/article/details/51005463
http://blog.csdn.net/qq_32183461/article/details/50705953
http://blog.csdn.net/chen_tongsheng/article/details/55211772
http://blog.csdn.net/summonlight/article/details/61427968
一、题目
寒假作业
现在小学的数学题目也不是那么好玩的。看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每个方块代表1~13中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
一、照猫画虎
直接上dfs,说实话,才看了一天的DFS,只知道它是深度优先搜索算法,对图进行遍历。又看了几个蓝桥杯dfs方面的例题,对dfs的了解就只有这么多。
#include<stdio.h> int a[13] = { 0 };//标记12个位置对应的数,a[0]不用 int book[14] = { 0 };//标记1-13有没有被使用过,book[1]=0表示数值1没有被使用,book[1]=1表示数值1被使用了,book[0]不用 int count = 0;//满足条件的总格式初始化为0 void dfs(int x) { if (x > 12)//如果12个数都已经填满了,进行判断 { if ((a[10] / a[11] == a[12]) && (a[10] % a[11] == 0)&& (a[7] * a[8] == a[9]) && (a[1] + a[2] == a[3]) && (a[4] - a[5] == a[6])) { count++;//满足条件,数量加一 for (int i = 1; i <= 12; i++)//输出满足条件的值,查看结果 { printf("%d ", a[i]); } printf("\n"); return; } } for (int i = 1; i <= 13; i++)//从数字1到13,看有没有没用过的数字,没有用过就填入当前格子 { if (book[i] == 0)//表示i这个数字没有用过 { book[i] = 1;//将book[i]置1,表示i这个数被用了 a[x] = i;//当前格子值a[x]置为i dfs(x + 1);//进行下一次搜索,填入下一个数字 book[i] = 0;//从后向前回溯,将book[i]置0。这一行非常重要,千万不能掉。 } } } int main() { dfs(1); printf("%d\n", count); return 0; }
看了六角填数和方格填数的例子,仿照着写的。最开始程序运行的时候半天不出结果,心理很担心是不是写错了,运行了关闭,关闭了运行。后来看了其他人寒假作业的例子,才发现直接这样一下子判断所有条件,运行次数太多,速度太慢。回寝室之后,好奇到底要运行多久,就搞台式机跑了一下,20多分钟出的结果。没有想象中那么久,但就普通程序来说,也等不起。
补充:20多分钟是Debug的结果,后来换成Release,10分钟出结果,但还是有点久。
二、加一点初始条件看看
因为直接运行要很久,想起了六角填数,那题有12个数,3个数的初始值已经定了,程序运行很快就出结果。就差几个出,运行时间差别怎么就那么大了??就想着能不能像六角填数那样,我自己先给他赋值一个初始条件,看看运行结果是那样,运行时间要多久。
根据题目给了实例,我令a[1]=6,a[2]=7,a[3]=13,相应地book[6]=1,book[7]=1,book[13]=1,预期结果应该是16。
//加初始条件 #include<stdio.h> int a[13] = { 0 };//标记12个位置对应的数,a[0]不用 int book[14] = { 0 };//标记1-13有没有被使用过,book[1]=0表示数值1没有被使用,book[1]=1表示数值1被使用了,book[0]不用 int count = 0;//满足条件的总格式初始化为0 void dfs(int x) { if (x == 1 || x == 2 || x == 3)//直接进行下一次搜索 { dfs(x + 1); return; } if (x > 12)//如果12个数都已经填满了,进行判断 { if ((a[10] / a[11] == a[12]) && (a[10] % a[11] == 0) && (a[7] * a[8] == a[9]) && (a[1] + a[2] == a[3]) && (a[4] - a[5] == a[6])) { count++;//满足条件,数量加一 for (int i = 1; i <= 12; i++)//输出满足条件的值,查看结果 { printf("%d ", a[i]); } printf("\n"); return; } } for (int i = 1; i <= 13; i++)//从数字1到13,看有没有没用过的数字,没有用过就填入当前格子 { if (book[i] == 0)//表示i这个数字没有用过 { book[i] = 1;//将book[i]置1,表示i这个数被用了 a[x] = i;//当前格子值a[x]置为i dfs(x + 1);//进行下一次搜索,填入下一个数字 book[i] = 0;//从后向前回溯,将book[i]置0。这一行非常重要,千万不能掉。 } } } int main() { a[1] = 6; a[2] = 7; a[3] = 13; book[6] = 1; book[7] = 1; book[13] = 1; dfs(1); printf("%d\n", count); return 0; }
基本秒出结果
感觉自己好弱智,别人都说这是基本入门算法。。。呜呜呜。
三、分开判断
看了一下别人的代码,分开判断,秒出结果。
//三、分开判断 #include<stdio.h> double a[13] = {0}; int book[14] = {0}; int count = 0; int j = 0; void dfs(int x) { if (x == 4) { if (a[1] + a[2] != a[3]) return; } if (x == 7) { if (a[4] - a[5] != a[6]) return; } if (x == 10) { if (a[7] * a[8] != a[9]) return; } if (x > 12) { if (a[10] / a[11] == a[12]) { count++; } return; } for (int i = 1; i <= 13; i++) { if (book[i] == 0) { book[i] = 1; a[x] = i; dfs(x + 1); book[i] = 0; } } } int main() { dfs(1); printf("%d\n", count); return 0; }
四、全排列
今天下午,接触到全排列算法。同学用java写的,2分钟就跑出结果了。我就照着写了一下。
//自己全排列 #include<stdio.h> int a[14] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13}; int count = 0; void swap(int *a, int*b) { int temp = *a; *a = *b; *b = temp; } void FullPermutation(int x) { if (x >= 13) { if ((a[11]*a[12]==a[10]) && (a[7] * a[8] == a[9]) && (a[1] + a[2] == a[3]) && (a[4] - a[5] == a[6])) { count++;//满足条件,数量加一 for (int i = 1; i <= 12; i++)//输出满足条件的值,查看结果 { printf("%d ", a[i]); } printf("\n"); return; } } for (int i = x; i < 14; i++) { swap(&a[i], &a[x]); FullPermutation(x + 1); swap(&a[i], &a[x]); } } int main(void) { FullPermutation(1); printf("%d\n", count); return 0; }程序写好后,在VS中运行,十几分钟半天不出结果。大爷的,别人java的2分钟就出结果了,我的C怎么这么久。就胡乱改代码,还是不行。后来在网上百度,无意中发现VS中Release比Debug要看,就换成了Release试试,结果2分钟就出结果了。呜呜呜,不容易呀。
`