写出一个 1 至 N的排列 a_i ,然后每次将相邻两个数相加,构成新的序列,再对新序列进行这样的操作,显然每次构成的序列都比上一次的序列长度少 1 ,直到只剩下一个数字位置。下面是一个例子:
3,1,2,4
4,3,6
7,9
16
最后得到 16这样一个数字。
现在想要倒着玩这样一个游戏,如果知道 N,知道最后得到的数字的大小 sum ,请你求出最初序列 a_i ,为 1至 N的一个排列。若答案有多种可能,则输出字典序最小的那一个。(注意:这里字典序指的是 1,2,3,4,5,6,7,8,9,10,11,12,而不是 1,10,11,12,2,3,4,5,6,7,8,9 )
输入
两个整数,n,sum(n<=12,sum<=10000)
输出
1~n的一个排列
样例
样例输入1
4 16
样例输出1
3 1 2 4
提示
3,2,1,4最后得到的和也为16,但是3,1,2,4字典序更小
一道DFS+剪枝,轻轻松松
#include<bits/stdc++.h>
using namespace std;
int c[15][15],a[15],b[15]= {0};
int n,m,flag=0;
void dfs(int k,int sum);
int main()
{
scanf("%d%d",&n,&m);
c[1][1]=1;
for (int i=2; i<=n; i++) { //杨辉三角
c[i][1]=c[i][i]=1;
for (int j=2; j<n; j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
}
dfs(1,0);
return 0;
}
void dfs(int k,int sum)
{
if (sum>m)
return; //剪枝
if (k>n) {
if (sum==m) {
flag=1;
for (int i=1; i<=n; i++)
cout<<a[i]<<" ";
exit(0);
}
return;
}
for (int i=1; i<=n; i++) { //全排列
if (b[i]) continue;
b[i]=1;
a[k]=i;
dfs(k+1,sum+c[n][k]*i); //*该数
b[i]=0;
}
}
这里运用了杨辉三角,有兴趣的可以自己算一下,找找规律