寒假作业问题(DFS方法)

问题:

寒假作业
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
每个方块代表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解决:

#include<iostream>
using namespace std;
int total = 0, num[14], flag[14];               //舍弃第0位不用,1-13位,flag为标志位
void dfs(int n)
{
	if (n >= 14)                                //不满足,直接退出
		return;
	else if (n == 4 && num[1] + num[2] != num[3]) //列出一个可能的算式之后判定其是否满足对应的判定条件
		return;
	else if (n == 7 && num[4] - num[5] != num[6])
		return;
	else if (n == 10 && num[7] * num[8] != num[9])
		return;
	else if (n == 13)
	{
		if (num[12] * num[11] == num[10])
			total++;
	}
	for (int i = 1; i < 14; i++)
	{
		if (flag[i] == 0)                         //标志位为0,表示该数字还未被使用,也就是顶点未被访问
		{
			num[n] = i;
			flag[i] = 1;
			dfs(n + 1);                           //递归
			flag[i] = 0;
		}
	}

}
int main()
{
	dfs(1);
	cout << total << endl;
	return 0;
}

感悟:

对于这种取不同的数字来建立等式,dfs大都能快速而有效的解决。经过这两天的练习,dfs算法已初窥门径,还需要继续加强练习。

猜你喜欢

转载自blog.csdn.net/Crazy__1/article/details/88668612