算法题——深度优先搜索

DFS的模板

  判断能否从一个点走到终点

bool dfs(v) {
	if (v为终点) {
		return true;
	}

	if (v是走过的点) {
		return false;
	}

	//v是未走过的点
	操作1:将v标记为旧点(已经走过的点)
	操作2:对和v相邻的每个节点u,执行如下操作 {
		if (dfs(u) == true) {
			//从v到u,最终可以到终点
			return true;
		}
	}
	//从v不能走到终点
	return false;
}

  

  判断从一个点能否走到终点,如果能的话,记录路径

Node path[MAX_LEN]; //记录路径
int depth; //记录深度(走的步数)

bool dfs(v) {
	if (v为终点) {
		path[depth] = v;
		return true;
	}

	if (v是走过的点) {
		return false;
	}

	//v是未走过的点
	操作1:将v标记为旧点(已经走过的点)
	path[depth] = v;
	++depth;

	操作2:对和v相邻的每个节点u,执行如下操作 {
		if (dfs(u) == true) {
			//从v到u,最终可以到终点
			return true;
		}
	}
	//从v不能走到终点,回退一步,深度减1
	--depth;
	return false;
}

int main(){
	depth = 0;
	if (dfs(起点)) { //如果能走到终点,就打印路径
		for (int i = 0; i < depth; i++) {
			cout << path << endl;
		}
	}
}

  

例题1:城堡问题

  http://bailian.openjudge.cn/practice/2815

#include<iostream>
#include<algorithm>
using namespace std;

int R, C; //行列数
int rooms[60][60];  //输入每个房间的情况:1、西墙;2、北墙;4、东墙;8、南墙
int color[60][60];  //房间是否已经走过
int maxRoomArea = 0;  //最大的房间面积
int roomNum =0;     //房间数量
int roomArea;       //用来记录每个房间的面积j

void dfs(int i, int j)  // 从room[i][j]开始进行dfs操作
{
    if (color[i][j]){  //已经走过的点
        return;
    }

    //否则是没有走过的点
    ++roomArea;  //房间面积加1
    color[i][j] = roomNum;   //给这个没有走过的房间做标记(表示已经走过了)

    if ((rooms[i][j] & 1) == 0) {  //西边没有墙
        dfs(i, j-1);
    }

    if ((rooms[i][j] & 2) == 0) { //北边没有墙
        dfs(i-1, j);
    }

    if ((rooms[i][j] & 4) == 0) {  //东边没有墙
        dfs(i, j+1);
    }

    if ((rooms[i][j] & 8) == 0) {
        dfs(i+1, j);
    }
}

int main()
{
    cin >> R >> C;
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            cin >> rooms[i][j];
            color[i][j] = 0;
        }
    }

    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            //循环遍历图中的每个点,如果color[i][j]为0,表示这里可以作为一个新房间的起点
            //如果color[i][j]为1,表示这个房间已经走过了,那么就不再进行搜索了
            if (!color[i][j]) {
                ++roomNum;   //房间的数量加1
                roomArea = 0;  //当前房间的最大面积
                dfs(i, j);
                maxRoomArea = max(roomArea, maxRoomArea);
            }
        }
    }

    cout << roomNum << endl;
    cout<< maxRoomArea << endl;
}

  

例题2:踩方块

  http://bailian.openjudge.cn/practice/4103/

#include<iostream>
using namespace std;
int visited[30][50];

int ways(int i, int j, int n) {
    if (n == 0){
        return 1;
    }
    visited[i][j] = 1; // 将此步标记为1
    int num = 0;
    if (! visited[i][j-1]) { //向西走
        num += ways(i, j-1, n-1);
    }

    if (! visited[i][j+1]) {
        num += ways(i, j+1, n-1);
    }

    if(! visited[i+1][j]) {
        num += ways(i+1, j, n-1);
    }

    visited[i][j] = 0; //离开的时候,将此步标记为未走过
    return num;
}

int main(){
    int n;
    while (cin >> n) {
        cout << ways(0, 25, n) << endl;
    }
    return 0;
}

  

例题3:Roads

  http://poj.org/problem?id=1724

 

 

例题4:泉水淹没的面积

Description
有一个泉眼,由于当地的地势不均匀,有高有低,这个泉眼不断的向外溶出水来,这意味着这里在不久的将来将会一个小湖。水往低处流,凡是比泉眼地势低或者等于的地方都会被水淹没,地势高的地方水不会越过。而且又因为泉水比较弱,当所有地势低的 地方被淹没后,水位将不会上涨,一直定在跟泉眼一样的水位上。 所有的地图都是一个矩形,并按照坐标系分成了一个个小方格,Leyni知道每个方格的具体高度。我们假定当水留到地图边界时,不会留出地图外,现在他想通过这些数据分析出,将来这里将会出现一个多大面积的湖
Input
有若干组数据,每组数据的第一行有四个整数n,m,p1,p2(0<n,m,p1,p2<=1000),n和m表示当前地图的长和宽,(p1,p2)表示当前地图的泉眼位置。在n*m的矩阵里每个数字表示这每一个对应坐标的高度。
Output
输出对应地图中会有多少个格子被水充满。
Sample Input
3 5 2 3
3 4 1 5 1
2 3 3 4 7
4 1 4 1 1
Sample Output
6

   

#include<iostream>
#include<stack>
#include<cstring>
using namespace std;

int arr[1000][1000];
bool visit[1000][1000];
int n, m, x, y;
int h;   //泉眼的高度
int sum = 0;

int dfs(int i, int j) {
    if (visit[i][j]){  //已经走过
        return 0;
    }
    visit[i][j] = true;
    sum += 1;
    if (i-1 >= 1 && arr[i-1][j] <= h) {  //上
        dfs(i-1,j);
    }

    if (i+1 <=n && arr[i+1][j] <= h) {
        dfs(i+1, j);
    }

    if (j-1 >= 1 && arr[i][j-1] <= h) {
        dfs(i, j-1);
    }
    if (j+1 <=n && arr[i][j+1] <= h) {
        dfs(i, j+1);
    }
    return sum;
}
int main()
{

    while(cin >> n >> m >> x >> y) {
        memset(visit, false, sizeof(visit));

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> arr[i][j];
            }
        }

        h = arr[x][y];

        dfs(x, y);
        cout << sum << endl;
    }

    return 0;
}

  

posted @ 2018-08-16 00:59  寻觅beyond  阅读(254)  评论(0)    收藏  举报
返回顶部