DFS深搜学习感悟及习题(白书经典题 和 POJ-2386 Lake Counting )

1、深搜的概念

深搜DFS简单来说就是暴力的变形。它会遍历所有可能的答案,对每一种可能都会进行尝试。简单来说就是,搜索下去,回溯上来。(白书的定义:从某个状态开始,不断转移状态,直到转移到无法转移,然后退回到前一步的状态,如此不断重复,直到找到最终的解)

2、部分和问题

给定整数,a1、a2、...、an,判断是否可以从中选出若干数,使他们的和恰好为k。
n<10,k < 1000000;
输入
n = 4
a ={ 1,2,4,7 }
k = 15
输出
No

首先一开始看到这个题目我并不理解,作为一个大一新生,九月一号前都没见过c语言的学生。理解起来的确十分费劲。但是有一天确实看懂了,总的来说,深搜的答案分布和二叉树十分类似,你需要一个标记数(字结点),还需要一个验证的sum(跳出回溯的条件),也就是说深搜是建立在《数据结构》这本书上的(有的学校会学到的),所以想要熟练掌握深搜,就要熟悉二叉树。

Accpect:

#include <iostream>

using namespace std;

int n,k;
int a[10];
bool dfs (int i,int sum)
{
    if(i == n) return sum == k;//结束条件
    if(dfs(i+1,sum)) return true;//相当于二叉树遍历
    if(dfs(i+1,sum+a[i])) return true;//继续遍历
    return false;//如果都没有就返回false
}
int main()
{
    cin >> n >> k ;
    for(int i = 0;i < n;i++)
    cin >> a[i];
    if(dfs(0,0))
    cout << "Yes" << endl;
    else
    cout << "No" << endl;
    return 0;
}

3、八连通问题(POJ - 2386)

Lake Counting
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 40331 Accepted: 20005

Description

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.

Given a diagram of Farmer John's field, determine how many ponds he has.

Input

* Line 1: Two space-separated integers: N and M

* Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

Output

* Line 1: The number of ponds in Farmer John's field.

Sample Input

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

Sample Output

3

Hint

OUTPUT DETAILS:

There are three ponds: one in the upper left, one in the lower left,and one along the right side.

Source

AC:

开始用的linux下的vim,使用不习惯,打了好几次才打出来ac代码,虽然以前是有这个实力的,表示vim的规则好多,对新手并不友好,所以一开始还是建议使用Cold Blocks或者dev c++。打代码过程中一定要注意细节,不要被细节影响了全局,不管是语法错误还是语义错误。


#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

int m,n;
char a[105][105];
void dfs(int x,int y)
{
    a[x][y] = '.';
    for(int i = -1;i <= 1;i++)
    {
        for(int j = -1;j <= 1;j++)
        {
            int nx = x + i,ny = y + j;
            if(nx >= 0 && nx < m && ny >= 0 && ny < n && a[nx][ny] == 'W')
            {
                dfs(nx,ny);
            }
        }
    }
    return;

}
int main()
{
   int res = 0;
    cin >> m >> n;
        for(int i = 0;i < m;i++)
        {
            for(int j = 0;j < n;j++)
            {
                cin >> a[i][j];
            }
        }
        for(int i = 0;i < m;i++)
        {
            for(int j = 0;j < n;j++)
            {
                if(a[i][j]=='W')
                {
                    dfs(i,j);
                    res++;
                }
            }
        }
        cout << res << endl;
    return 0;
}
认真,专注,永不放弃,绝不言敗!
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值