这又是一道自己没写出来的题
然后参考了dalao们的题解
自己写了一遍
一开始也想到了要全排列 然后也知道肯定会tle
参考了dalao们的题解后理解的做法:
①构造杨辉三角
②每次全排列枚举不用进行到底,可以通过每一步求和进行剪枝(若部分和已经超过总和则return)
做法一代码:
#include<bits/stdc++.h>
using namespace std;
int a[20]; //数字(该数组可有可无)
int vis[20]; //记录下标数字是否被用过
int sj[20][20]; //杨辉三角数组
int ans[20]; //记录答案数字
int n, sum;
void init(){ //初始化函数
for(int i=1; i<=n; i++){ //初始化a数组,其实可以直接用数字,但是懒得改了= =
a[i] = i;
}
sj[1][1] = 1; //初始化杨辉三角
for(int i=2; i<=n; i++){
for(int j=1; j<=i; j++){
sj[i][j] = sj[i-1][j-1] + sj[i-1][j];
}
}
}
void print(){ //打印函数
for(int i=1; i<=n; i++){
cout<<ans[i]<<" ";
}
cout<<endl;
}
int dfs(int x, int p, int cnt){
if(cnt>sum) //若部分和大于综合则剪枝
return 0;
if(x==n){
if(cnt==sum){
ans[x] = p; //记录答案数字
return 1;
}else{
return 0;
}
}else{
vis[p] = 1; //记录该数字已被使用
for(int i=1; i<=n; i++){
if(!vis[i]&&dfs(x+1, a[i], cnt+sj[n][x+1]*a[i])){ //判断数字是否被使用过 和 递归判断找出下一个数字并计算部分和
ans[x] = p; //记录答案数字
return 1;
}
}
vis[p] = 0; //若数字不满足条件没使用,则取消记录
return 0;
}
}
int main(){
cin>>n>>sum;
init();
// for(int i=1; i<=n; i++){ 打印杨辉三角
// for(int j=1; j<=i; j++){
// cout<<sj[i][j]<<" ";
// }
// cout<<endl;
// }
if(dfs(0, 0, 0)){ //如果满足条件则打印答案
print();
}
return 0;
}
参考了另外一个dalao的stl题解,自己也实现了一遍
做法二代码:
#include<bits/stdc++.h>
using namespace std;
int sj[20][20]; //杨辉三角
int a[20]; //数字 (这里这个数组是必须的, 因为stl是对数组进行全排列)
int n, sum;
void init(){
for(int i=1; i<=n; i++){ //初始化数组a
a[i] = i;
}
sj[1][1] = 1; //初始化杨辉三角
for(int i=2; i<=n; i++){
for(int j=1; j<=i; j++){
sj[i][j] = sj[i-1][j-1] + sj[i-1][j];
}
}
}
int cmp(int a, int b){ //排序判断函数 从大到小
return a>b;
}
void solve(){
do{
int flag = 0; //判断数组是否满足条件 0表示满足条件, 1表示不满足条件
int cnt = 0; //记录部分和
for(int i=1; i<=n; i++){
cnt += sj[n][i]*a[i]; //求部分和
if(cnt>sum){ //判断部分和是否大于总和
flag = 1; //flag改为不满足条件
sort(a+i, a+n+1, cmp); //对a数组i位置后面的数字从大到小进行排序,跳过后面的全排列
break; //这是因为stl全排列是按字典序的,如果前i个不满足条件,则
//以i为首的排列都不满足条件,对a数组排序之后就可以跳过这些排列,实现剪枝
}
}
if(flag) //不满足条件跳过
continue;
if(cnt==sum){ //条件满足输出a数组并返回
for(int i=1; i<=n; i++){
cout<<a[i]<<" ";
}
return;
}
}while(next_permutation(a+1, a+n+1));
}
int main(){
cin>>n>>sum;
init();
solve();
return 0;
}