DFS
本题思路不难想,就是将1-n的所有数字的全排列枚举出来,因为数字序列添加的方法已经给出了,找出其中规律即可得到合并数列的公式。然后把每个数列合并后的结果跟目标值比较
思路以及代码
/*
给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,
显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。
例如:
3 1 2 4
4 3 6
7 9
16
现在如果知道N和最后得到的数字sum,请求出最初序列a[i],
为1~N的一个排列。若有多种答案,则输出字典序最小的那一个。数据保证有解。
样例输入
4 16
样例输出
3 1 2 4
数据规模和约定
0<n<=10
*/
#include<iostream>
using namespace std;
const int N=12;
int a[N];
int n,sum;
int p[N];//用于判断某个元素是否被用过
int get_a=0;
int c_nm(int n,int m){
//求组合数
int fenzi=1;
int fenmu1=1;
int fenmu2=1;
for(int i=1;i<=n;i++)
fenzi*=i;
for(int i=1;i<=m;i++)
fenmu1*=i;
for(int i=1;i<=(n-m);i++)
fenmu2*=i;
return fenzi/(fenmu1*fenmu2);
}
int judge(int a[]){
//给出数组a[]
int tot=0;
for(int i=1;i<=n;i++){
tot+=c_nm(n-1,i-1)*a[i];
}
if(tot==sum)
return 1;
else
return 0;
}
void dfs(int layer,int a[]){
//层数layer用于判断是否数字有n个
//a[]数组存储可能的答案
if(layer==n+1){
if(judge(a)){
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
get_a=1;//说明得到答案
return ;
}
return ;
}
for(int i=1;i<=n;i++){
if(get_a)
return ;
if(p[i]==0){//某个元素没有被使用过
a[layer]=i;
p[i]=1;
dfs(layer+1,a);
p[i]=0;
}
}
}
int main(){
cin>>n>>sum;
dfs(1,a);
return 0;
}