题意:已知有N个数分别为1-N,如下图为4个数。相邻两两相加直至只剩下一个数,下图的结果就是16。
3 1 2 4
4 3 6
7 9
16
现在反过来看,告诉你数的个数N和最终结果,问这N个数的初始序列是什么。求出字典序最小的初始序列。上图的初始序列也可以是3 2 1 4,但这不是字典序最小。
分析:这题用全排列的方式非常容易做。首先初始化数组为1-N,然后用STL提供的按字典序生成全排列的函数next_permutation即可枚举全排列。对于每一组数,通过计算可以知道它是否能得出已知结果。最先找到的那组数就是字典序最小的值。
1 /* 2 input: 3 4 16 4 output: 5 3 1 2 4 6 */ 7 #include <cstdio> 8 #include <algorithm> 9 10 using namespace std; 11 12 const int MAX_N = 10; 13 14 //输入 15 int N, finalSum; 16 17 int a[MAX_N][MAX_N]; //保存序列以及计算序列结果 18 19 int calulate(){ 20 //计算序列所得的最后和 21 for(int i = 1; i < N; i ++){ 22 for(int j = 0; j < N - i; j ++){ 23 a[i][j] = a[i - 1][j] + a[i - 1][j + 1]; 24 } 25 } 26 return a[N - 1][0]; 27 } 28 29 void solve(){ 30 //初始化序列 31 for(int i = 0; i < N; i ++) 32 a[0][i] = i + 1; 33 //按字典序枚举全排列 34 do{ 35 int sum = calulate(); 36 if(sum == finalSum){ 37 printf("%d", a[0][0]); 38 for(int i = 1; i < N; i ++){ 39 printf(" %d", a[0][i]); 40 } 41 printf(" "); 42 break; 43 } 44 }while(next_permutation(a[0], a[0] + N)); 45 46 } 47 48 int main(int argc, char const *argv[]){ 49 50 scanf("%d %d", &N, &finalSum); 51 solve(); 52 53 return 0; 54 }