题目
从 1,2,3,⋯,30 这 30 个数中选 8 个数出来,使得和值为 200。问有多少种选法。
输出70.
思路
可行性剪枝:
要么选要么不选,如果选的多,退出,和超过200退出,选到最后一个数,进行判断,满足条件ans+1.
重复性剪枝:
选出来的数的位置是递增的,用一个参数来记录上一次选取的数的位置,此次选择从这个数之后开始选取,最后选出来的方案不会重复
代码
#include <iostream>
using namespace std;
int n, k, sum, ans;
int a[40];
void dfs(int i, int cnt, int s) {
if(cnt>k){
return ;
}
if(s>sum){
return ;
}
if (i == n) {
if (cnt == k && s == sum) {
ans++;
}
return;
}
dfs(i + 1, cnt, s);
dfs(i + 1, cnt + 1, s + a[i]);
}
int main() {
n = 30;
k = 8;
sum = 200;
for (int i = 0; i < 30; i++) {
a[i] = i + 1;
}
ans = 0;
dfs(0, 0, 0);
cout << ans << endl;
return 0;
}
#include <iostream>
using namespace std;
int n, k, sum, ans;
int a[40];
bool xuan[40];
void dfs(int s, int cnt,int pos) {
if(s>sum||cnt>k){
return ;
}
if (s == sum && cnt == k) {
ans++;
}
for (int i = pos; i < n; i++) {
if (!xuan[i]) {
xuan[i] = 1;
dfs(s + a[i], cnt + 1,i+1);
xuan[i] = 0;
}
}
}
int main() {
n = 30;
k = 8;
sum = 200;
for (int i = 0; i < 30; i++) {
a[i] = i + 1;
}
ans = 0;
dfs(0, 0,0);
cout << ans << endl;
return 0;
}