P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目如图,我们可以轻松写出一个dfs的选数代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int, int>;
const int N = 20 + 5;
int n, k, ans = 0;
int p[N], a[N];
bool st[N];
bool isprime(int sum) {
if (sum == 2) return true;
for (int i = 2; i <= sum / i; i++) {
if (sum % i == 0) {
return false;
}
}
return true;
}
void dfs(int u) {
if (u == k) {
int sum = 0;
for (int i = 0; i < u; i++) {
sum += p[i];
}
if (isprime(sum)) {
ans++;
}
}
for (int i = 0; i < n; i++) {
if (!st[i]) {
st[i] = true;
p[u] = a[i];
dfs(u + 1);
st[i] = false;
}
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cin >> n >> k;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
dfs(0);
cout << ans;
return 0;
}
运行,结果是6,但是正确答案是1,那我们不妨思考一下为什么会输出6。
3+7+19=29.但是dubug一下发现输出了6次29。很容易联想到这是三个数排列的顺序有6种,说明结果将换了顺序的三个数也当成了一组不同解。那么如何避免重复呢?
我们可以给dfs函数增加一个参数start,每次取值从start开始,每次递归i+1。
这样每次选数都不会选到目前这个数前面的,保证了组合的唯一性。
// Problem: P1036 [NOIP2002 普及组] 选数
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1036
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
using PII = pair<int, int>;
const int N = 20 + 5;
int n, k, ans = 0;
int p[N], a[N];
bool isprime(int sum) {
if (sum == 2) return true;
for (int i = 2; i <= sum / i; i++) {
if (sum % i == 0) {
return false;
}
}
return true;
}
void dfs(int u, int start) {
if (u == k) {
int sum = 0;
for (int i = 0; i < k; i++) {
sum += p[i];
}
if (isprime(sum)) {
ans++;
}
}
for (int i = start; i < n; i++) {
p[u] = a[i];
dfs(u + 1, i + 1);
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
cin >> n >> k;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
dfs(0, 0);
cout << ans;
return 0;
}
/*
* _oo0oo_
* o8888888o
* 88" . "88
* (| -_- |)
* 0\ = /0
* ___/`---'\___
* .' \\| |// '.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' |_/ |
* \ .-\__ '-' ___/-. /
* ___'. .' /--.--\ `. .'___
* ."" '< `.___\_<|>_/___.' >' "".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `_. \_ __\ /__ _/ .-` / /
* =====`-.____`.___ \_____/___.-`___.-'=====
* `=---='
*
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* 佛祖保佑 永不宕机 永无BUG
*/