P2404 自然數的拆分問題c++題解

YCU_poison發表於2020-10-05

P2404 自然數的拆分問題

題目描述
任何一個大於1的自然數n,總可以拆分成若干個小於n的自然數之和。現在給你一個自然數n,要求你求出n的拆分成一些數字的和。每個拆分後的序列中的數字從小到大排序。然後你需要輸出這些序列,其中字典序小的序列需要優先輸出。

輸入格式
輸入:待拆分的自然數n。

輸出格式
輸出:若干數的加法式子。

輸入輸出樣例
輸入
7
輸出
1+1+1+1+1+1+1
1+1+1+1+1+2
1+1+1+1+3
1+1+1+2+2
1+1+1+4
1+1+2+3
1+1+5
1+2+2+2
1+2+4
1+3+3
1+6
2+2+3
2+5
3+4

這就是一個簡單的求各個數求和,問滿足條件的式子有多少個?
道理大家都懂,但是怎麼用程式碼來實現呢,首先我們觀察樣例可以看到拆分的自然數總是大於或者等前一位數,所以我們要定義一個變數來儲存前一個數的資訊,避免重複尋找相同的式子,
當然我們需要知道當前式子之和為多少
以及我們要操作的數是第幾位
並用一個陣列儲存這若干個自然數

void backtrack(int n, int sum, int i, int b[], int qs);	
//n為要拆分的數
//sum為式子數的總和
//i為當前操作是第i位數
//b為該若干個數
//qs前一個數的值

然後在進行遞迴就行了,在遞迴的時候我們是從qs開始一直到n-1進行迴圈的,如果超出了n的值就退出遞迴。

#include<bits/stdc++.h>
using namespace std;
void backtrack(int n, int sum, int i, int b[], int qs) {
	if(n == sum) {	//兩個值相等表示找到了一個這樣的式子
		for(int j = 1; j <= i-2; j++) {
			cout << b[j] << "+";
		}
		cout << b[i-1] <<endl;
		return ;
	}
	if(i > n+1) return ;	//超出了值退出遞迴
	
	for(int j = qs; j <= n-1; j++) {
		b[i] = j;
		backtrack(n, sum+j, i+1, b, j);
		b[i] = 0;
	}
}
int main() {
	int n;
	int b[10];
	cin >> n;
	memset(b, 0, sizeof(b));
	backtrack(n, 0, 1, b, 1);
} 

相關文章