深度优先搜索(DFS)
从某个状态开始,不断转移状态,直到无法转移,然后退回前一步状态,继续转移到其他状态,直到找到最终的解。深度优先搜索采用递归函数实现比较简单。
例
给定整数a[1],a[2],…,a[n],判断是否可以从中选出若干数,使它们和为k。
限制条件:
- 1<=n<=20
- -108<=a[i]<=108
- -108<=k<=108
输入
n=4
a={1,2,4,7}
k=13
输出
yes
从a[1]开始按顺序每项选择加或不加,全部n项决定完后判断和是否为k。
程序复杂度分析 2n+1 => O(2n)
#include <stdio.h>
int a[20];
int n, k;
bool dfs(int i, int sum) {
if (i == n) return sum == k; //全部n项决定完后判断和是否为k。
if (dfs(i + 1, sum)) return true; //选择不加a[i]
if (dfs(i + 1, sum + a[i])) return true; //选择加a[i]
return false; //无论是否加a[i]都不等于k,返回false
}
void solve() {
if (dfs(0, 0)) printf("yes\n"); //从第一项开始调用dfs
else printf("No\n");
}
int main()
{
scanf_s("%d", &n); //输入
for (int i = 0; i < n; i++) {
scanf_s("%d", &a[i]);
}
scanf_s("%d", &k);
solve();
}
深度优先搜索从最初状态出发,遍历所有可以达到的状态,由此可以堆所有状态进行操作,或列举出所有状态
例
有一个N*M的园子,雨后积水。八连通的积水视为连在一起,为一个水坑。求园里总共有多少水坑。
+++
+w+
+++
加号是相对w的八连通方向
限制条件
- N,M<=100
输入
N=10,M=12
园子如下图(‘W’表示积水,’.’表示没有积水)
W . . . . . . . . WW .
. WWW . . . . . WWW
. . . . WW . . . WW .
. . . . . . . . . WW .
. . W . . . . . . W . .
. W . W . . . . . WW .
W. W . W . . . . . W .
. W . W . . . . . . W .
. . W . . . . . . . W .
(程序中输入按行输入,之间不带空格)
输出
3
从任意W开始,不停地将相邻W用’.‘代替,一次DFS后与这个W相连接的全部W被替换为’.’。当地图中全部W被替换,DFS次数就是水坑数。
程序复杂度分析 O(8 * N * M)=O(N * M)
#include<stdio.h>
#pragma warning(disable : 4996)
int N, M;
char field[100]