P1036 [NOIP2002 普及组] 选数---之深度优先搜索(DFS)

1. .深度优先搜索,是一种在开发爬虫早期使用较多的方法,他的目的是达到被搜索结构的叶节点。

2..深度优先搜索是属于图的一种算法,最近也学到了图这种数据结构,英文缩写是DFS即Depth First Search。其过程简要来说就是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。

3..算法框架

所有的搜索算法从其最终的算法实现上来看,都可以划分成两个部分──控制结构和产生系统。正如前面所说的,搜索算法简而言之就是穷举所有可能情况并找到合适的答案,所以最基本的问题就是罗列出所有可能的情况,这其实就是一种产生式系统。我们将所要解答的问题划分成若干个阶段或者步骤,当一个阶段计算完毕,下面往往有多种可选选择,所有的选择共同组成了问题的解空间,对搜索算法而言,将所有的阶段或步骤画出来就类似是树的结构(如图)。从根开始计算,到找到位于某个节点的解,回溯法(深度优先搜索)作为最基本的搜索算法,其采用了一种“一只向下走,走不通就掉头”的思想(体会“回溯”二字),相当于采用了先根遍历的方法来构造搜索树。
 

其实就算说完这些,然后去做题还是什么都不会,不要害怕,做题就是慢慢磨练,没有谁一开始就会的,好,接下来,我们来看一下题:

[NOIP2002 普及组] 选数 - 洛谷

 看完这个题之后,我就想到了一个我之前做过的题,不知道你们有没有做过{{{彩票}}}这个题,

(其实也是我自己太傻了,居然会把这俩题搞混)

彩票题意如下:

 

 

 然后彩票的代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,a[60],ans[60];
void dfs(int num,int start) {
	if(num==6) {
		for(int i=0; i<6; i++) printf("%d ",ans[i]);
		printf("\n");
		return;
	}
	for(int i=start; i<n; i++) {
 
		ans[num]=a[i];
		dfs(num+1,i+1);
 
	}
}
int main() {
	while(scanf("%d",&n)&&n) {
		
		for(int i=0; i<n; i++)
			cin>>a[i];
		sort(a,a+n);
		dfs(0,0);
		cout<<ans;
	}
}

看似这两题好像差别不大,所以我也就仿照这个代码来写了,试了一下水,果然还是不行,然后经过短暂思考之后,的确,两个题虽然看似差别不大,但重点很不同(是我太傻,),我们先看一下选数的代码:

#include<iostream>
#include<cmath>
using namespace std;
int n, k;
int a[500];
int f[1002];
int ans = 0;
int sum = 0;
bool cmp(int x)
{
	for (int i = 2; i <= sqrt(x) ; i++)
		if (x % i == 0)
			return 0;
	return 1;
}
void dfs(int s,int num, int start)
{
	if (num == k)
	{
		//for (int i = 0; i < k; i++) sum += f[i];
		if (cmp(s) == 1) 
			ans++;
		//return;
	}
	else {
		for (int i = start; i < n; i++)
		{
			//f[num] = a[i];
			dfs(s+a[i], num + 1, i + 1);
		}
	}
}
int main()
{
	cin >> n >> k;
	for (int i = 0; i < n; i++)
		cin >> a[i];
	//ans = 0;
	dfs(0, 0, 0);
	cout << ans;
	return 0;
}

这两个题,怎么说呢,彩票吧,是要k个数中的其中6个数,然后排列组合,首先选出6个数,其实是和选数所想要的思想是一样的,选数只是把所选的数求和,判断是不是素数,只要是素数我的ans就肯定要++的,而彩票不同,我注释掉的就是按照彩票打了一遍,是行不通的,千万不要上当。

当然选数这个题也不难,就是把数学中的c(n,k),把每个组合试一遍,遇见符合的计数器加1即可,最后输出就完了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值