蓝桥杯刷题——数字游戏(搜索)

641 阅读2分钟

「这是我参与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;
}