DFS deep optimization search

DFS deep optimization search

DFS algorithm

Thought: Keep going deep until you find a solution or you can’t go on

It is similar to the first root traversal of the tree. Just don't hit the south wall and don't look back

模板一:
DFS(dep,..)//dep代表目前DFS的深度
{
	if(找到解||走不下去)
	{
		...
		return;
	}
	DFS(dep+1,..)//枚举下一种情况
}

模板二:
DFS(dep,..)
{	
	if(判断条件)
	return;
	for(扩展转态)
	{
		判断合法;
		记录;
		DFS(dep+1,...)
		回溯;
	}
}

DFS traversal graph

1. Starting from v0 in the figure, visit v0.

2. Find the first unvisited adjacent point of v0 and visit the vertex. With this vertex as the new vertex, repeat this step until the vertex just visited has no unvisited adjacent points.

3. Return to the previously visited vertex that still has unvisited adjacent points, and continue to visit the next unvisited leading node of this vertex.

4. Repeat steps 2 and 3 until all vertices are visited and the search ends.

v0->v2->v4->v6->v1->v5->v3

v0
v2
v1
v3
v4
v5
v6

DFS question type


One: data type

Prime Ring Problem

Title

Given a number n, enclose the numbers 1~n into a circle. The requirement: The sum of two adjacent numbers is a prime number.

0<n<20

Output:

  • The direction of the numbers is the same (the same clockwise or the same counterclockwise), and the arrangement is not repeated
  • When there is only one number (n==1), output 1
  • Output Case k: (k is the number of data groups), each group of output (except the first one) has a blank line before

Ideas

Before each recursion, determine whether the sum of the first two numbers is a prime number, because it is a ring, the last number and the first number must also satisfy

Before DFS, you can use prime numbers to sieve, find prime numbers within 50, where n is 20, and the sum of the largest two prime numbers is less than 50

Code

#include<bits/stdc++.h> 
using namespace std;
const int MAX=50;
int prime[25];//素数数组 
bool vis[25]; //访问数组 
int n;// 个数 
int ans[MAX];//解答输出数组 
void Prime_set()  //筛法求素数 
{
    //Isprime 0、 IsNotprime 1  
    for(int i = 2; i<=sqrt(MAX) ;++ i)
        if(prime[i] == 0)
		{
            for(int j = 2;i*j<=MAX;++j)
                prime[i*j] = 1;
        }
    prime[1] = 0,vis[1]=true;//1虽然不是素数,但在此假设为0,将vis[1]设为true即不会遍历到1 
}
void DFS(int depth)
{
    if(prime[ans[depth-1]+ans[depth-2]]!=0) return ;  //前两个数之和不是素数退出 
    if(depth==n+1&&prime[ans[depth-1]+ans[1]]!=0) return ; //当选到最后一个数时,第一个数和最后一个数之和不是素数时退出 

    if(depth==n+1)  //选到最后一个数,输出 
    {
        for(int i=1;i<=n;i++) 
        {
            if(i==1) cout<<ans[i]; 
            else cout<<" "<<ans[i]; 
        }
            cout<<endl;
    }

    for(int i=2;i<=n;i++)   //把1~n按照一定顺序(DFS求得)填入数组ans 
    {
        if(!vis[i]) 
        {
            vis[i]=true;
            ans[depth]=i;
            DFS(depth+1);
            vis[i]=false;
        }
    }
}
int main(){
    int t=1; 
    Prime_set();
    while(cin>>n)
    {
        cout<<"Case "<<t++<<":"<<endl;
        memset(vis,false,sizeof(vis));
        memset(ans,0,sizeof(ans));
        ans[1] = 1;//1永远是首元素 
        if(n==1) cout<<"1"<<endl;
        else 
            DFS(2);//1永远是首元素,从2开始DFS ;也防止之后depth-2<0 
        cout<<endl;
    }   
    return 0;
}

Title description: choose the number

Known n integers x1, x2,..., xn x_n x**n and 1 integer k (k<n). From n integers, optionally k integers are added together to obtain a series of sums respectively. For example, when n=4, k=3, and 4 integers are 3, 7, 12, 19, all the combinations and their sum are:

3+7+12=22

3+7+19=29

7+12+19=38

3+12+19=34

Now, you are required to calculate how many kinds of sums are prime numbers.

For example, in the above example, only one kind of sum is prime: 3+7+19=29

#include<bits/stdc++.h>
using namespace std;
int a[10005],sum=0,ans=0;
int n,k;
int sushu(int f)
{
	for(int i=2;i*i<=f;i++)
	{
		if(f%i==0)
		return 0;
	}
	return 1;	
} 
void dfs(int x,int y)//x表示差几个数,y表示选到a[y] 
{
	if(x==0)
	ans+=sushu(sum);
	else
	{
		y++;
		for(int i=y;i<=n;i++)
		{
			sum+=a[i];
			x--;
			dfs(x,i);
			sum-=a[i];//回溯 
			++x;
		}
	}
}  
int main()
{
	cin>>n>>k;
	for(int i=1;i<=n;i++)
	cin>>a[i];
	dfs(k,0);
	cout<<ans<<endl;
	getchar();
    getchar();
    return 0;
}

Two: Graphic

Path in the matrix

Please design a function to judge whether there is a path containing all characters of a string in a matrix.

The path can start from any grid in the matrix, and each step can move one grid to the left, right, up, and down in the matrix.

If a path passes through a certain grid in the matrix, it cannot enter this grid again afterwards.

note:

  • The path entered is not empty;
  • All characters appearing are uppercase English letters

Sample

matrix=
[
  ["A","B","C","E"],
  ["S","F","C","S"],
  ["A","D","E","E"]
]

str="BCCE" , return "true" 

str="ASAE" , return "false"

CODE:

class Solution {
public:
    bool hasPath(vector<vector<char>>& matrix, string &str) 
    {
        for(int i=0;i<matrix.size();i++)
        {
            for(int j=0;j<matrix[i].size();j++)
            {
                if(dfs(matrix,str,0,i,j))//对每一个点深搜,起点不一样
                return true;
            }
        }
        return false;
    }
    
    bool dfs (vector<vector<char>>& matrix,string &str,int u,int i,int j )
    {
        if(matrix[i][j]!=str[u])return false;//不满足
        if(u==str.size()-1)return true;//找到了一条路径满足
        char t=matrix[i][j];//回溯需要
        matrix[i][j]='*';
        int dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};//方向向量
        for(int m=0;m<4;m++)
        {
            int a=i+dx[m],b=j+dy[m];
            if (a >= 0 && a < matrix.size() && b >= 0 && b < matrix[a].size()) 
           {
                if(dfs(matrix,str,u+1,a,b))
            return true;
           }
        }
        matrix[i][j]=t;//回溯
        return false;
        
    }
    
};

Out of the maze

Xiao Ming is playing a game now, and the maze is an N*M matrix.

Xiao Ming’s starting point is represented by "S" on the map, the end point is represented by "E", obstacles are represented by "#", and open spaces are represented by ".".

Obstacles cannot pass. If Xiao Ming is now at the point (x, y), then the next step can only go to one of the four adjacent grids: (x+1, y), (x-1, y), (x, y +1), (x, y-1);

Xiao Ming wants to know whether he can walk from the beginning to the end now

Sample input
3 3
S..
..E
...
3 3
S##
###
##E
Sample output
Yes
No

AC code

#include<bits/stdc++.h>
using namespace std;
int n,m,flag=0,a,b;//flag是标记能否到达 
const int MAX=510;
char s[MAX][MAX];
int dx[]={-1, 1, 0, 0}, dy[]={0, 0, -1, 1};//方向向量 

void DFS(int i,int j)
{
	if(flag||s[i][j]=='#'||i<0||i>=n||j<0||j>=m)//判出 
	return;
	if(s[i][j]=='E')//到达终点 
	{
		flag=1;
		return;
	}
	s[i][j]='#';//走过了的路不回头 
	for(int e=0; e<4; e++)
    	DFS(i+dx[e], j+dy[e]);//继续深搜 
}

int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		flag=0;//每一组数据重新赋值为0 
		for(int i=0;i<n;i++)
		scanf("%s",s[i]);
			for(int i=0;i<n;i++)
				for(int j=0;j<m;j++)
					if(s[i][j]=='S')a=i,b=j;//起点标记 
		DFS(a,b);
		if(flag)
		 puts("Yes");
		else
		puts("No");
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_46029533/article/details/109378863