「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
题目
给定一个1~N的排列a[i],每次将相邻两个数相加,得到新序列,再对新序列重复这样的操作,显然每次得到的序列都比上一次的序列长度少1,最终只剩一个数字。例如
3 1 2 4
4 3 6
7 9
16
现在给定N和最后的一个数字,要求求出1~N的数的排列,如果有多个排列,那么就输出字典序最小的那个排列数。
思路
让我们求出一列数据的一个排列,那么首先,我们可以暴力搜索,把这列数据的全部排列都列出来,然后一个个试过去,看是否满足条件,如果满足条件。这个全排列我们可以自己写,但是c++的STL库中有个功能非常强大的全排列函数next_permutation()。
全排列函数
这个函数的参数就是数组的起点还有终点,如果你设置的起点是数组中的第二个数,那么第一个参数就是a+1,设置的终点是数组中的第5个数,那么第二个参数就是a+5,而这个函数也是要配合do while结构来使用的,每一次都会重新排列一次,直到全部排列完全。并且只排列设置的起点和终点直接的数,包括设置的起点和终点。
排列后的数组判断
b是排列后的数组
j=n;
while(j>1){
for(i=0;i<j-1;i++){
b[i]=b[i]+b[i+1];
}
j--;
}
每次序列都减少一,最终剩下一个数字b[0]得出答案。
总代码
#include<bits/stdc++.h>
using namespace std;
main(){
int a[50],b[50],n,sum,i,j;
cin>>n>>sum;
j=n;
for(i=0;i<n;i++){
a[i]=i+1;
}
do{
for(i=0;i<n;i++){
b[i]=a[i];
}
while(j>1){
for(i=0;i<j-1;i++){
b[i]=b[i]+b[i+1];
}
j--;
}
j=n;
if(b[0]==sum){
for(i=0;i<n;i++){
cout<<a[i]<<" ";
return 0;
}
}while(next_permutation(a,a+n));
return 0;
}