1. 程式人生 > >整數劃分(遞迴,附程式執行過程)

整數劃分(遞迴,附程式執行過程)

問題描述: 任何一個大於1的自然數N,總可以拆分成若干個小於n的自然數之和。

輸入: n

輸出:按字典序輸出具體方案。

我們以 n = 4 為例說明一下執行過程, 下附程式碼

我們以 n = 4 為例說明一下執行過程
閱讀本段 一定要注意各個變數值的變化

cin >> n = 4, 進入func函式
此時 s = 4, t = 1;
for 迴圈 i = a[1-1] = 1
1 < 4 => a[1] = 1, s = 3;
s = 3 != 0 遞迴進入下一層 ***我們在這裡做一下標記,方便回溯

第二層 s = 3, t = 2
i = a[2-1] = 1 	不知道為什麼看第五行
i < s, i < n => a[2] = 1, s = 2;
s = 2 != 0 繼續遞迴進入下一層 	***

第三層 s = 2, t = 3;
步驟類似前面的
最後 s = 1, a[3] = 1
s = 1 != 0 繼續遞迴進入下一層 ****

第四層 s = 1, t = 4;
這一層for迴圈只執行一次 因為 i = 1, s = 1
a[4] = 1, s = 0;
print(t);	輸出了 4 = 1+1+1+1;

開始回溯
我們注意到 在第三層 s = 2, i = 1, 故for迴圈執行兩次
第二次for迴圈 i = 2, s = 2
這一層變數的值 i = 2,s = 2, t = 3, a[0]~a[4] 都是 1
迴圈體裡a[3] = i = 2, s = 2 - 2 = 0
執行print(t) 要注意一下print函式輸出是a[1] 到 a[t]
所以輸出的是 4 = 1 + 1 + 2;	下面的輸出原因也是一樣

至此第三層的for迴圈也執行完畢
變數值 a[0] = a[1] = a[2] = a[4] = 1, a[3] = 2;

回溯到第二層, 第二層的for迴圈只執行了一次
但是本層初始值 i = 1, s = 3, t = 2, 所以還有兩次for迴圈沒有執行
第二次for迴圈 i = 2
迴圈體內 i < n, a[2] = 2, s = 3 - 2 = 1
s != 0
注意了, 我們又要遞迴了	*** 標記一下, 一會回溯到此處

第五次遞迴
a[0] = 1, a[1] = 1, a[2] = 2, a[3] = 2, a[4] = 1;
s = 1, t = 3
初始i = a[2] = 2	注意前文陣列a中值的變化 a[2] 已經是2了
i = 2, 但是 s = 1 	for迴圈不執行

直接回溯到剛才標記到地方, 進行第三次for迴圈
第二層第三次for迴圈 i = 3, s = 3, t = 2
3 < 4 => a[2] = 3  s = 3 - 3 = 0;
s = 0, 執行print(t) 輸出 4 = 1 + 3

到此處 第二層的for迴圈執行完畢
a[0] = 1, a[1] = 1, a[2] = 3, a[3] = 2, a[4] = 1

回溯到第一層, 第一層初始 i = 1, s = 4, 應執行四次for迴圈
現執行第二次for迴圈
i = 2, s = 4, t = 1
2 < 4 => a[1] = 2, s = 4 - 2 = 2
s = 2 != 0 進行遞迴

第六次遞迴
s = 2, t = 2
a[0] = 1, a[1] = 2, a[2] =3, a[3] = 2, a[4] = 1
初始 i = a[2-1] = 2,  s = 2	 執行一次for迴圈
i = 2 < 4 => a[2] = 2, s = 2 - 2 = 0;
s = 0 執行print(t) 輸出 4 = 2 + 2	// 在此處所有情況以輸出完畢
執行完畢, 回溯

回溯到第一層
執行第三次for迴圈
i = 3, s = 4, t = 1
i < n =>	a[1] = 3, s = 4 - 3 = 1;
s = 1 != 0 進行遞迴

第七次遞迴
a[0] = 1, a[1] = 3, a[2] = 3, a[3] = 2, a[4] = 1;
初始 s = 1, t = 2, i = a[2-1] = 3
i > s, 不執行for迴圈,直接回溯

回溯到第一層
執行第四次for迴圈
i = 4, s = 4, t = 1
迴圈體內 i = 4, n = 4, i < n 不成立
往下不在執行, 跳出迴圈

至此所有程式執行完畢, 返回到主函式


#include <iostream>
using namespace std;
const int MAXN = 100000+7;

int n, total = 0;
int a[MAXN] = {1};	//	初始a[0] = 1, 其餘全為0

void print(int t)
{
	total ++;
	cout << n << "=";
	for(int i=1; i<=t; i++)
	{
		if(i == t)	// 最後一個數時執行這一步
			cout << a[i] << endl;
		else
			cout << a[i] << "+";
	}
}
int func(int s, int t)
{
	for(int i=a[t-1]; i<=s; i++)
	{
		if(i < n)
		{
			a[t] = i;
			s = s - i;
			if(s == 0)
				print(t);
			else
				func(s, t+1);
			s += i;
		}
	}
	return 0;
}

int main()
{
	cin >> n;
	func(n, 1);
	cout << total << endl;


	return 0;
}