深度优先搜索(DFS)是搜索的手段之一。它从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直至找到最终的解。
部分和问题:
给定整数a1、a2、...、an,判断是否可以从中选出若干数,使它们的和恰好为k。
分析:
从a1开始按顺序决定每个数加或不加,在全部n个数都决定后再判断它们的和是不是k即可。因为状态数是2n+1(每个数都有加和不加两种情况),所以复杂度是O(2n)。

代码如下:
/*
题目描述:能否找到数组a中的元素相加之和等于指定的数k
解决方法:深度优先搜索(dfs)对每个元素组合进行遍历
*/
#include<iostream>
using namespace std;
int a[100],k,n;
//已经从前i项得到了和sum,然后对于i项之后的进行分支
bool dfs(int i,int sum){
//如果前n项都计算过了,则返回sum是否与k相等
if(i==n) return sum == k;
//不加上a[i]的情况
if(dfs(i+1,sum)) return true;
//加上a[i]的情况
if(dfs(i+1,sum+a[i])) return true;
//加不加a[i],都被无法与k相等,则返回false
return false;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
cin>>k;
if(dfs(0,0)){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
return 0;
}
部分和问题是DFS的基本题,现在我们稍微深入,求解poj2386,水洼问题
题目描述:
给定一个矩阵(m*n),其中W表示有水,. 表示干地,现给出定义在W周围(包括该W)的8个坐标位置(上下左右,左上左下右上右下)有W存在则形成水洼(水洼具有传递性),求这个矩阵中有多少个水洼?
样例输入:
10 12 W........WW. .WWW.....WWW ....WW...WW. .........WW. .........W.. ..W......W.. .W.W.....WW. W.W.W.....W. .W.W......W. ..W.......W.
样例输出:
3
分析:可从任一个W开始,判定周围是否存在W,进行深搜,并将遍历到的W都改为.,那么最后进行深搜的次数便是水洼的个数。
#include<iostream>
#include<cstring>
using namespace std;
int m,n;
char pool[101][101];//题中矩阵
void dfs(int x,int y){
//首先将其改为干地
pool[x][y]='.';
//对每个方向进行遍历
for(int i=-1;i<=1;i++){
for(int j=-1;j<=1;j++){
int nx=x+i,ny=y+j;
//若为'W',则沿着继续搜索
if(nx>=0&&ny>=0&&nx<m&&ny<n&&pool[nx][ny]=='W'){
dfs(nx,ny);
}
}
}
}
int find(){
int count = 0;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
//遍历整个矩阵,若为'W',启动深搜,并计数
if(pool[i][j]=='W'){
dfs(i,j);
count++;
}
}
}
return count;
}
int main(){
cin>>m>>n;
for(int i=0;i<m;i++){
cin>>pool[i];
}
cout<<find()<<endl;
return 0;
}
来源:https://www.cnblogs.com/tz346125264/p/7704921.html