题目描述
某君有n个互不相同的正整数,现在他要从这n个正整数之中无重复地选取任意个数,并仅通过加法凑出整数X。求某君有多少种不同的方案来凑出整数X。
输入
第一行,输入两个整数n,X(1≤n≤20,1≤X≤2000)。
接下来输入n个整数,每个整数不超过100。
输出
输出一个整数,表示能凑出X的方案数。
样例输入
6 6
1 2 3 4 5 6
样例输出
4
提示
一共有 4 种方案:
6
1 5
1 2 3
2 4
看提示像子集生成问题,这道题目子集里的数和为X为限制条件。
可以看子集生成的代码上做调整
&
0&0=0; 0&1=0; 1&0=0; 1&1=1; 即:两位同时为“1”,结果才为“1”,否则为0
|
0|0=0; 0|1=1; 1|0=1; 1|1=1;即 :参加运算的两个对象只要有一个为1,其值为1。
^
0 ^ 0=0; 0 ^ 1=1; 1^ 0=1; 1^1=0; 即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。
详细查看这里:非常详细
https://blog.csdn.net/weixin_43736974/article/details/84543970
#include <bits/stdc++.h>
using namespace std;
void print_subset(int n){
for(int i=0; i< (1<<n); i++) {
//i:0~2^n,每个i的二进制数对应一个子集。
for(int j=0;j<n;j++) //打印一个子集,即打印i的二进制数中所有的1。
if(i & (1<<j))
cout<< j << " ";
cout << endl;
}
}
int main(){
int n;
cin>>n; // n:集合中元素的总数量。
print_subset(n); // 打印所有的子集。
}
一、
#include <bits/stdc++.h>
using namespace std;
int n,x,a[25],cnt=0;
int main(){
cin >>n >>x;
for(int i=0;i<n;i++)
cin >> a[i];
for(int i=0;i<(1<<n);i++){ //(1<<n)=2^n i 的范围 (0~2^n-1)
int sum=0;
for(int j=0;j<n;j++){
if(i&(1<<j)) //如果是1运行
sum+=a[j];
}
if(sum==x)cnt++;
}
cout << cnt;
return 0;
}
二、
递归的方法,跟权排列是不一样的,不要混淆,为小菜菜,解出来不容易,是从装载问题得到启发
不过看不懂的话打开软件自己调试一下哈!
#include <bits/stdc++.h>
using namespace std;
int n,x,sum=0,cnt=0;
int a[25],b[25]={0};
void dfs(int p,int q){
if(q==x){
cnt++; //计算方案个数
return;
}
else{
for(int i=p;i<n;i++){
if(b[i]==0){ //如果为0表示该下标对应的a数组的数字没有用过
b[i]=1;
dfs(i+1,q+a[i]);
b[i]=0; //回溯把它变为0;
}
}
}
}
int main(){
cin >>n >>x;
for(int i=0;i<n;i++)
cin >> a[i];
dfs(0,0);
cout << cnt;
return 0;
}