DFS 深搜 选数问题
- 看一看题 👉P1036 选数👇
[NOIP2002 普及组] 选数
题目描述
已知 n n n 个整数 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn,以及 1 1 1 个整数 k k k( k < n k<n k<n)。从 n n n 个整数中任选 k k k 个整数相加,可分别得到一系列的和。例如当 n = 4 n=4 n=4, k = 3 k=3 k=3, 4 4 4 个整数分别为 3 , 7 , 12 , 19 3,7,12,19 3,7,12,19 时,可得全部的组合与它们的和为:
3 + 7 + 12 = 22 3+7+12=22 3+7+12=22
3 + 7 + 19 = 29 3+7+19=29 3+7+19=29
7 + 12 + 19 = 38 7+12+19=38 7+12+19=38
3 + 12 + 19 = 34 3+12+19=34 3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数: 3 + 7 + 19 = 29 3+7+19=29 3+7+19=29。
输入格式
第一行两个空格隔开的整数 n , k n,k n,k( 1 ≤ n ≤ 20 1 \le n \le 20 1≤n≤20, k < n k<n k<n)。
第二行 n n n 个整数,分别为 x 1 , x 2 , ⋯ , x n x_1,x_2,\cdots,x_n x1,x2,⋯,xn( 1 ≤ x i ≤ 5 × 1 0 6 1 \le x_i \le 5\times 10^6 1≤xi≤5×106)。
输出格式
输出一个整数,表示种类数。
样例 #1
样例输入 #1
4 3
3 7 12 19
样例输出 #1
1
提示
【题目来源】
NOIP 2002 普及组第二题
代码与解析
- 这个题与其他DFS相比,最大的问题是如何找出所有不重复的情况
- 从最特殊的角度看,我们可以发现,4个数中任选3个,那所有情况中,就可使后一个数大于前一个数,且每一种情况都有一个数不选,就组成了这四种情况。
- 比如 7 8 5 6这四个数
> - 5 6 7
> - 6 7 8
> - 5 7 8
> - 5 6 8
- 用DFS写的话,可以再加一个参数来维护,使得每次搜索时,后一个数总要比前一个数字大。
- 具体这样操作👇代码里有注释
#include<bits/stdc++.h>
#define IOS std::ios::sync_with_stdio(false),cout.tie(0),cin.tie(0);//加快输入输出
using namespace std;
const int N = 1e6;
int n,m,arr[N],arr2[N],num[N],zhishu = 0,maxn = 0;
bool vis[N];//标记数组
void check(int x)//检验质数函数
{
int suc = 1;//标记初始为真
if(x != 1)
{
for(int i = 2;i <= x/i;i++)//筛质数,筛到一半,即i^2 = x,i <= 根号x
{
if(x % i == 0)//判断是否是x的因数
{
suc = 0;//标为假
break;
}
}
}
if(suc == 1) zhishu++;//质数数量累加
if(suc == 0) return ;
}
void dfs(int now,int sum,int maxn)//深搜
{
arr[sum] = now;//当前搜索的数存到临时数组
if(sum == m)//判断边界
{
int a = 0;
for(int i = 1;i <= m;i++) a += arr[i];//求和
check(a);//检验质数
}
for(int i = sum+1;i <= n;i++)//从更深一层开始循环
{
if(i > maxn)//当后一个数比前一个大时
{
dfs(arr2[i],sum+1,max(maxn,i));//从更深的一层搜索,维护较大的一个数
}
}
}
int main()
{
IOS;//加快输入输出
cin>>n>>m;//读入n,m
for(int i = 1;i <= n;i++) cin>>arr2[i];//n个数存到数组里
for(int i = 1;i <= n;i++)
{
dfs(arr2[i],1,max(maxn,i));//开始搜索
}
cout<<zhishu;//输出质数个数
}
- 本题对于初学者稍有难度,但可以参考其他入门的DFS题目,熟悉了基本模板,无论写起来还是理解起来都会更加简便
- 对于初次学习dfs和bfs的同学一定不要急,将代码自己多写几遍,没事就看看,慢慢就理解了😊