题目
从 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;
}