1-9九个数字不重复组成一个三位数加法算式,求出所有组合

本文介绍如何使用深度优先搜索算法解决一个数学谜题:将1-9的数字填入特定格式的算式中,使等式成立。通过详细的算法解析和C++代码示例,展示了如何遍历所有可能的组合并找出符合条件的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:
将1-9的9个数字不重复的填入[ ][ ][ ] + [ ][ ][ ] = [ ][ ][ ],使得等式成立
如 173 + 286 = 459 且 将 286 + 173 = 459 视为同一种,问满足这样条件的情况有几种

问题解法:
将9个不重复数字填入到9个位置并且满足等式成立条件,可以看做求9个数组的全排列,只要全排列满足 前3个数字 + 中间3个数字 = 最后3个数字即可;
为简化问题,我们先看123这三个数字的全排列,很简单,123这三个数字的全排列是
123 ;132 ; 213 ; 231; 312 ; 321
我是这么做的,假设将1 2 3 这三个数放到 3 个盒子中,那么所有可能数即为全排列数,我们约定 每一次往盒子里面放数的时候,都从小到大放, 比如第一个盒子,我们放1;第二个盒子因为1已经没了,所以我们放2;第三个盒子我们只能放3了;现在全部放完。但显然全排列情况不止这一种,所以我们将第三个盒子中的3取出,但取出3后还是只能放3,与刚刚的情况重复,所以我们将第二个盒子中的2也取出来,此时我们手里面有2 3 ;向第二个盒子里面放数,因为放2这种情况已经出现过,所以我们放3,第三个盒子只能放2,得出的全排列为 132;然后继续弹出,将1 2 3 这三个数均弹出,现在我们往第一个盒子里面放2(由小到大放),第二个盒子里面放1,第三个盒子里面放3,得出全排列为 213 ;…
依次类推,直到第一个盒子里面准备放4为止;(不可能放4,因为我们手里面只有3个数)
现在我们将上述过程图形化表示出来;是这样的:

在这里插入图片描述
发现了什么?发现了每一次搜索但是从第一层到最后一层,先纵向搜索,然后再横向搜索,而这正是深度优先搜索的核心思想

当我们解决了第一个盒子的放那个数据的问题后,需要解决第二个盒子的放数据问题,而解决第二个盒子的存放数据问题和解决第一个盒子的存放数据问题的步骤是完全一致的;所以核心是如何解决第一个盒子的存放数据问题;
因为每一次放数据都不能重复,所以我们需要知道哪些数据已经被放入盒子里,哪些没有;因为数字1 2 3 ,所以我们用一个数组来标记book[4] = {0}; 0 号元素弃之不用(方便编程);book[1] ==0表示1还未被使用,当1已经被使用后 置book[1] = 1,
解决了哪些元素还可以用的问题,接下来就是解决程序何时停止的问题;当我们准备往第四个盒子里面放数据时,说明前3个盒子里面已经有数据,程序应该停止

知道了如何进行 1 2 3 三个数字的全排列,1- 9的全排列也是类似的;废话不多说,直接上代码

C++实现代码如下:

#include "iostream"
using namespace std;
#include "vector"
//问题描述,ABC + EFG = HIJ,其中A...J对应1-9中的某个数,使得等号成立,求出可能的情况
//EFG + ABC = HIJ和上面的算是一种情况

//这一问题可以用暴力枚举循环,因为某个数被用过之后就不能在被别的地方用,所以需要用桶标记法来标记该数是否被用过
//但这就需要嵌套10层循环,然后如果如果用到了某个数,则将桶置为1,最后看所以桶之和是否为9,为9说明每个数都被用了一次

//但你是否觉得过于复杂,所以我们引入了 深度优先搜索算法,该算法的 基本思路是:重点是解决当前的问题,然后解决下一个问题的步骤与解决该问题的步骤一致

/*
简单模型

判断边界,不满足边界条件,则跳出深度优先搜索
尝试每一种可能(for循环)
{
	继续下一步
}
返回


*/

//解题思路:将9个空格看做待填入数的9个空格,每次填入一个,直到填满,判断是否符合条件,符合条件则+1,则推到上一个格子处重新填数


void DFS(int step,vector<int> & v1, vector<int> & v2,int &count)//v1表示每一步填入的数;v2为标记,相当于上面的book
{
	//边界条件
	//因为是9个数,从1开始,所以如果step > 9准备往第10个盒子里放数据;说明此轮搜索完毕,前9个盒子里面有数据,判断是否符合  相加和相等条件;如何跳出(边界条件,控制递归结束)
	if (step > 9)
	{
		if (v1[1] * 100 + v1[2] * 10 + v1[3] + v1[4] * 100 + v1[5] * 10 + v1[6] == v1[7] * 100 + v1[8] * 10 + v1[9])
		{
			count++;

			printf("%d%d%d+%d%d%d = %d%d%d\n", v1[1], v1[2], v1[3], v1[4], v1[5], v1[6], v1[7], v1[8], v1[9]);
		}
		return;
	}
	//开始解决第一步填入的数
	for (int i = 1;i <= 9;i++)
	{
		if (v2[i] == 0)
		{
			v1[step] = i;//将i填入第一步step中,然后置其标记为1
			v2[i] = 1;//表明i已经被用了,不能再用了
			//然后开始第二步
			DFS(step + 1, v1, v2, count);
			//释放已经用过的数,否则下次循环不能用
			v2[i] = 0;
		}
	}
	return;
}



int main()
{
	vector<int> v1(10,INT_MAX);
	vector<int> v2(10, 0);
	int count = 0;
	DFS(1,v1,v2,count);
	cout << "满足相加和相等条件的情况有"<<count / 2 << endl; //因为173 + 286 = 459 与 286 + 173 = 459为同一种
	system("pause");
	return 0;
}

程序运行部分结果
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值