dfs---------------------深度优先搜索

            深度优先搜索就是不断地重复深入的过程直到找到你需要结果或者越界为止

通常的方法就是把每一种可能都期尝试一遍(一般用for循环遍历)。当前这一步解决之后便进入下一步dfs(step+1)。

下一步的解决方案是完全一样的。下面给出基本模型

void dfs(int step)
{
    判断边界
    尝试每一种可能 for(i=1;i<=n;i++)
    {
         继续下一步 dfs(step+1);   
    }
    返回
}

            实现方法

         DFS一般用递归来实现,改变当层状态不断深入,直到找到答案或者已经可以知道这样下去无法得到答案,再返回到上一个状态(恢复该层状态)继续递归。保证每一个点(每一种可能性)都遍历过,但是并不能保证答案是最优解(如最小值,最短路等,这些一般用BFS实现)。

                                                                                                                                                                                                                     如图,在这棵树上做dfs为 1 2 4 5 3 6 7        

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       

下面我举几个栗子

1.

A - Oil Deposits

 POJ - 1562 

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.

Input

The input contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket. 
 

Output

are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5 
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

Sample Output

0
1
2
2

题目是英文的但是意思还是好懂的

   有一片区域,人为的给他划分成若干块小区域,如果有石油我们给这个·小区域标上@,如果没有,标上*;

不论是横的竖的斜的,只要两块小区域连在一起就可以认为他们属于同一片油田。题目就是要我们统计有多少块油田

 思路

从头开始找,找到一块就搜溹他的八个方向,找到所有能找到的油田并打上标记,这样我们称为一趟

我们只要记录走了几趟就好了;

AC代码

#include<iostream> 
#include<cstdio>
#include<algorithm>
using namespace std;
int xy[8][2]={1,0,1,-1,1,1,0,1,0,-1,-1,0,-1,1,-1,-1}; //八个方向。
char s[110][110];
int ans,m,n;
void dfs(int x,int y){
	s[x][y] = '*';             // 将@变为*
	for(int i = 0;i < 8; i++){
		int a = x + xy[i][0];
		int b = y + xy[i][1];
		if(a < m && a >= 0 && b < n && b >= 0 && s[a][b] == '@')
				dfs(a,b);
	}
	return;                        
}
int main(){
	while(cin >> m >> n && n && m){
		ans = 0;
		for(int  i = 0;i < m; i++)
			scanf("%s",s[i]);
		for(int i = 0; i < m;i++)
			for(int j = 0; j < n;j++){//遍历每个点
				if(s[i][j] == '@'){//判断该点是不是@,如果是的话,dfs。
					dfs(i,j);
					ans++;
				}
			} 
		cout << ans<<endl;
	}
	return 0;
}

例二

D - Prime Ring Problem

 HDU - 1016 

A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. 

Note: the number of first circle should always be 1. 

Input

n (0 < n < 20). 

Output

The output format is shown as sample below. Each row represents a series of circle numbers in the ring beginning from 1 clockwisely and anticlockwisely. The order of numbers must satisfy the above requirements. Print solutions in lexicographical order. 

You are to write a program that completes above process. 

Print a blank line after each case. 

Sample Input

6
8

Sample Output

Case 1:
1 4 3 2 5 6
1 6 5 2 3 4

Case 2:
1 2 3 8 5 6 7 4
1 2 5 8 3 4 7 6
1 4 7 6 5 8 3 2
1 6 7 4 3 8 5 2

题意

这个题就一个全排列的问题

只不过对排列的顺序有要求而已

就是相邻两个数相加为素数

AC代码

#include <bits/stdc++.h>

using namespace std;
int n;
struct node
{
	int mark;
	int num;
}stu[25];
int prime[12]={2,3,5,7,11,13,17,19,23,29,31,37};

int  dfs(int k)
{
	int flag;
	int i;
	if(k==n+1)
	{
		for(i=0;i<12;i++)
		{
			if((stu[k-1].num+1)==prime[i])
			{
				for(int j=1;j<n;j++)
					printf("%d ",stu[j].num);
				    printf("%d\n",stu[n].num);
			}
		 } 
		
	}
	else
	{
		for(i=2;i<=n;i++)
		{
			flag=0;
			for(int j=0;j<12;j++)
			{
				if((i+stu[k-1].num)==prime[j])
				flag=1;
			}
			if(stu[i].mark&&flag)
			{
				stu[i].mark=0;
				stu[k].num=i;
				dfs(k+1);
				stu[i].mark=1;
			}
		}
		
	 } 
	return 0;
}



int main()
{  
	int Case=1;
	while(cin>>n)
	{
		printf("Case %d:\n",Case++);
	    if(n==1)
	    {
	    	printf("1\n\n");
	    	continue;
		}
		
		stu[1].mark=0;
		for(int i=2;i<=n;i++)
            stu[i].mark=1;
		stu[1].num=1;
		dfs(2);
		printf("\n");
			
 	}	 
	return 0;
}

                                                        

猜你喜欢

转载自blog.csdn.net/weixin_42105529/article/details/81476213