P1036 [NOIP2002 普及组] 选数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思考
我的第一种思考是先用排序搜索搜到所有的情况,再在所有情况中找到符合条件的统计次数,但是忽略了这样会导致重复选择的问题,这道题的核心是选择而不是排序。
看了大佬的题解后感觉不讲原则来求这种选择的题很微妙,很有趣
接下来我就按照我的理解来解释不降原则吧
先看代码
#include <iostream>
#include <cmath>
using namespace std;
int n, k;
int a[25], vis[25];
int cnt = 0;
bool check(int x) {
if (x < 2)
return false;
for (int i = 2; i <= sqrt(x); i++) {
if (x % i == 0)
return false;
}
return true;
}
void dfs(int d, int sum, int stat) {
if (d == k) {
if (check(sum))
cnt++;
return;
}
for (int i = stat; i < n; i++) {
dfs(d+1,sum+a[i],i+1);
}
return ;
}
int main() {
cin >> n >> k;
for (int i = 0; i < n; i++)
cin >> a[i];
dfs(0, 0, 0);
cout << cnt;
return 0;
}
其中dfs用到了递增原则,原理差不多
例如5个数
1, 2 , 3,4, 5;
所有的情况
选五个 1,2,3,4,5
选四个 1,2,3,4 1,2,3,5 1,3,4,5 2,3,4,5
选三个 1,2,3 1,2,4 1,2,5 1,3,4 1,3,5 1,4,5
2,3,4 2,3,5 2,4,5
3,4,5
选两个 1,2 1,3 1,4 1,5
2,3 2,4 2,5
3,4 3,5
4,5
选一个 1
2
3
4
5
上述的所有情况都会在遍历的时候经历到;
关键的是,这里面选择的情况(选择的数字)没有相同的,而且涉及到所有的情况,即具有全面性和特异性;
为了更好的理解,我将建立一个三角形,来理解这些情况是怎么出现的;
还是以上面五个数字为例
1 2 3 4 5
2 3 4 5
3 4 5
4 5
5
第一层dfs star=0
此时
1 2 3 4 5
都可以作为开始
因为下一层的dfs(d+1,sum+a[i],i+1);
i+1很关键
意味着下一层的dfs将会从它的下一位开始,即不会下降,满足的递增原则
画图理解
1 2 3 4 5
2 3 4 5 什么也不选
3 4 5 什么也不选
4 5 什么也不选
5 什么也不选
从第一层选一个数,下一个只能斜着选择,而且最右边是什么也不选