Búsqueda de optimización profunda DFS

Búsqueda de optimización profunda DFS

Algoritmo DFS

Pensamiento: sigue profundizando hasta que encuentres una solución o no puedas continuar

Es similar al primer recorrido de raíz del árbol. Simplemente no golpees la pared sur y no mires atrás

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

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

Gráfico transversal DFS

1. A partir de v0 en la figura, visite v0.

2. Encuentre el primer punto adyacente no visitado de v0 y visite el vértice. Con este vértice como nuevo vértice, repita este paso hasta que el vértice recién visitado no tenga puntos adyacentes no visitados.

3. Regrese al vértice visitado anteriormente que todavía tiene puntos adyacentes no visitados y continúe visitando el siguiente nodo principal no visitado de este vértice.

4. Repita los pasos 2 y 3 hasta que se visiten todos los vértices y finalice la búsqueda.

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

v0
v2
v1
v3
v4
v5
v6

Tipo de pregunta DFS


Uno: tipo de datos

Problema del anillo primario

Título

Dado un número n, encierre los números 1 ~ n en un círculo El requisito: La suma de dos números adyacentes es un número primo.

0 <n <20

Salida:

  • La dirección de los números es la misma (la misma en el sentido de las agujas del reloj o en el sentido contrario a las agujas del reloj), y la disposición no se repite
  • Cuando solo hay un número (n == 1), salida 1
  • Caso de salida k: (k es el número de grupos de datos), cada grupo de salida (excepto el primero) tiene una línea en blanco antes

Ideas

Antes de cada recursión, determine si la suma de los dos primeros números es un número primo, ya que es un anillo, el último número y el primer número también deben satisfacer

Antes de DFS, puede usar números primos para tamizar, encontrar números primos dentro de 50, donde n es 20, y la suma de los dos números primos más grandes es menor que 50

Código

#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;
}

Descripción del título: elige el número

N enteros conocidos x1, x2, ..., xn x_n x ** n y 1 entero k (k <n). De n enteros, opcionalmente se suman k enteros para obtener una serie de sumas respectivamente. Por ejemplo, cuando n = 4, k = 3 y 4 enteros son 3, 7, 12, 19, todas las combinaciones y su suma son:

3 + 7 + 12 = 22

3 + 7 + 19 = 29

7 + 12 + 19 = 38

3 + 12 + 19 = 34

Ahora, debe calcular cuántos tipos de sumas son números primos.

Por ejemplo, en el ejemplo anterior, solo un tipo de suma es primo: 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;
}

Dos: Gráfico

Camino en la matriz

Diseñe una función para juzgar si existe una ruta que contenga todos los caracteres de una cadena en una matriz.

La ruta puede comenzar desde cualquier cuadrícula en la matriz, y cada paso puede mover una cuadrícula hacia la izquierda, derecha, arriba y abajo en la matriz.

Si una ruta pasa a través de una determinada cuadrícula en la matriz, no puede volver a ingresar a esta cuadrícula después.

Nota:

  • La ruta ingresada no está vacía;
  • Todos los caracteres que aparecen son letras mayúsculas en inglés

Muestra

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

str="BCCE" , return "true" 

str="ASAE" , return "false"

CÓDIGO:

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;
        
    }
    
};

Fuera del laberinto

Xiao Ming está jugando un juego ahora, y el laberinto es una matriz N * M.

El punto de partida de Xiao Ming está representado por "S" en el mapa, el punto final está representado por "E", los obstáculos están representados por "#" y los espacios abiertos están representados por ".".

Los obstáculos no pueden pasar. Si Xiao Ming está ahora en el punto (x, y), entonces el siguiente paso solo puede ir a una de las cuatro cuadrículas adyacentes: (x + 1, y), (x-1, y), (x, y +1), (x, y-1);

Xiao Ming quiere saber si ahora puede caminar desde el principio hasta el final.

Entrada de muestra
3 3
S..
..E
...
3 3
S##
###
##E
Salida de muestra
Yes
No

Código AC

#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;
}

Supongo que te gusta

Origin blog.csdn.net/qq_46029533/article/details/109378863
Recomendado
Clasificación