1-9九個數字不重複組成一個三位數加法算式,求出所有組合

問題描述:
將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;
}

程序運行部分結果
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章