POJ 3187 穷举

时间:2024-06-21 13:35:50

题意:已知有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即可枚举全排列。对于每一组数,通过计算可以知道它是否能得出已知结果。最先找到的那组数就是字典序最小的值。

 /*
input:
4 16
output:
3 1 2 4
*/
#include <cstdio>
#include <algorithm> using namespace std; const int MAX_N = ; //输入
int N, finalSum; int a[MAX_N][MAX_N]; //保存序列以及计算序列结果 int calulate(){
//计算序列所得的最后和
for(int i = ; i < N; i ++){
for(int j = ; j < N - i; j ++){
a[i][j] = a[i - ][j] + a[i - ][j + ];
}
}
return a[N - ][];
} void solve(){
//初始化序列
for(int i = ; i < N; i ++)
a[][i] = i + ;
//按字典序枚举全排列
do{
int sum = calulate();
if(sum == finalSum){
printf("%d", a[][]);
for(int i = ; i < N; i ++){
printf(" %d", a[][i]);
}
printf("\n");
break;
}
}while(next_permutation(a[], a[] + N)); } int main(int argc, char const *argv[]){ scanf("%d %d", &N, &finalSum);
solve(); return ;
}