1. 程式人生 > >五個整數任意組合(加減)得到1~122之間的數

五個整數任意組合(加減)得到1~122之間的數

//問題描述
/*
給定五個整數1,3,9,27,81,這個五個整數可以任意組合進行加減(可以是五個數中的部分相加),這五個數組合進行加減可以得到1~122之間的數, 任意輸入1~122之間的一個整數,得到其相應的組合,並且按照由大到小的順序輸出其表示式


    示例輸入輸出


    輸入:5


    輸出:9-3-1
*/


之前寫過一個華為上機題,五個數字相加任意組合成1~122之間的數,這幾天看到了,感覺當時寫的方法太挫了,居然是利用多層迴圈,那如果有更多數,或者數字個數不確定,那不就沒轍了。

對於這個數字任意組合,很容易想到的就是排列組合(輸出n個數字的所有排列)。類似,就可以用回溯的方法來實現。這裡回溯其實也就是直接搜尋,執行過程與利用多層迴圈實質相同,但對於解決問題比多層迴圈的挫辦法要實用得多。

程式碼與求n個數字的排列類似,也是到達最裡面一層判斷是否滿足條件,否則返回上一層,並更改這一層的狀態,繼續往下一層走。

#include <iostream>

using namespace std;
int weights[5] = {81,27,9,3,1};


void combine(int n, int sign[], int value)
{
	if (n == 5)
	{
		int sum = 0;
		for (int i = 0; i < 5; i++)
		{
			int tmp = weights[i]*sign[i];
			sum += tmp;
		}
		
		if (sum == value)
		{
			//輸出
			bool flag = false;
			for (int j = 0; j < 5; j++)
			{
				if (sign[j] != 0)
				{

					if (sign[j] == 1)
					{
						if (flag)
						{
							cout << "+";
						}
						cout << weights[j];
					}
					else if (sign[j] == -1)
					{
						cout << "-" << weights[j];
					}
									
					flag = true;
				}

			}
			cout << endl;
		}
	}
	else
	{
		sign[n] = 0; combine(n+1, sign, value);
		sign[n] = 1; combine(n+1, sign, value);
		sign[n] = -1; combine(n+1, sign, value);
		
	}
	
}



int main()
{
	int Value;
	int sign[5]; 
	while(cin>>Value)
	{
		combine(0, sign, Value);
	}
	
	
	return 0;
}