Pas de recherche en profondeur ? Lisez cet article sur la recherche en profondeur de l'explication détaillée de l'algorithme

avant-propos

Bonjour à tous, je suis Bubble, un passionné d'algorithmes. Il y a beaucoup de hauts et de bas et de "grandes montagnes" sur la route de l'apprentissage des algorithmes. Je pense que tout le monde a une compréhension profonde. Je pense qu'il y a plusieurs points très difficiles dans l'apprentissage des algorithmes, et ils en portent le poids Il s'agit d'une recherche en profondeur d'abord et d'une recherche en largeur Bien que je comprenne ce que cela signifie, je ne peux pas du tout taper le code et je ne peux pas écrire de questions de base, ce qui me rend très confus. Ce n'est pas le cas avec le triage que j'ai appris auparavant, pourquoi ? En fait, c'est parce que vous ne vous souvenez pas du modèle tout en comprenant l'algorithme. Il y a toujours un dicton en y qui est très bon. Vous ne construisez pas l'algorithme, vous apprenez à utiliser le modèle. Oui, c'est des dizaines de La cristallisation de la sagesse de divers scientifiques pendant des années, voire des centaines d'années, est définitivement difficile pour les débutants, c'est pourquoi l'article d'aujourd'hui est ici.

L'article d'aujourd'hui est juste pour aider les étudiants qui sont toujours coincés dans la recherche en profondeur et qui ne peuvent vraiment pas écrire de code. La lecture de cet article peut vous donner une expérience différente. Ici, j'imite la méthode d'analyse dp de style Yan et je crée la mienne. méthode simple en quatre étapes dfs, gardez à l'esprit les quatre étapes, le problème du labyrinthe, le problème de l'arrangement n'a pas peur de ne pas le faire du tout !

teneur

Résumé de l'algorithme

Exercice 1 : Batailles navales

Description du sujet

format d'entrée

format de sortie

Exercice 2 : Disposition

Description du sujet

format d'entrée

format de sortie

Résumer


Résumé de l'algorithme

Recherche en profondeur :

C'est une sorte de méthode de parcours de graphe, qui est implémentée par pile.La recherche en profondeur d'abord est similaire au parcours pré-ordonné des arbres.

En termes humains, son idée n'est pas de heurter le mur sud et de ne pas regarder en arrière, de continuer à marcher jusqu'à un point jusqu'à ce que vous ne puissiez plus aller, puis d'envisager d'autres directions jusqu'à ce que tous les points aient été traversés. De toute évidence, la recherche en profondeur est un processus récursif.

Peut-être que vous ne pouvez pas ressentir son charme juste en disant, jetons un œil à la photo ci-dessus.

Parce que le dessin du blogueur est trop moche, j'ai donc emprunté la structure de données de l'université du Zhejiang.Voici une photo, tous les points n'ont pas été visités.

 

Ensuite, nous partons du premier point, l'ampoule est allumée, si dans le code nous avons besoin d'un tableau pour garder une trace des chemins parcourus.

 

 Ensuite, nous sommes allés à droite et avons constaté que nous n'avions pas dépassé, puis nous sommes allés ici

 Une fois arrivé ici, vous constatez que vous ne pouvez qu'aller à gauche, puis continuer à aller à gauche

 À ce moment-là, nous avons constaté qu'il y avait deux voies à suivre, y a-t-il une hésitation ? Non, on a tous traversé à la fin, donc on a fini, choisissez le dessus, et c'est parti !

 

Après avoir marché, nous avons constaté qu'il n'y avait aucun moyen d'y aller, alors nous sommes retournés par le même chemin, à l'endroit où nous venions de faire notre choix.

 

Choisissez ensuite l'endroit où vous n'êtes jamais allé auparavant et continuez à marcher

 

Finir

Je crois que tout le monde peut voir clairement comment fonctionne la recherche en profondeur d'abord en regardant l'image, mais comment le code doit-il être écrit dans l'application réelle ? Nous présentons quelques exemples pour vous donner une meilleure compréhension de la recherche en profondeur d'abord.

Suivez notre méthode en quatre étapes, la première étape, enregistrez la carte, la direction, marquez le tableau

Tout le monde doit lire la question pour décider quoi stocker dans le tableau d'images, le tableau de direction et le tableau de marques. Ici, nous l'écrivons comme un tableau bidimensionnel normal et haut, bas, gauche et droite.

const int N = 10001;
int dx[] = {0,1,-1,0};
int dy[] = {1,0,0,-1};
int s[N][N];
bool vis[N][N];

La première couche est la plage de données, la deuxième couche et la troisième couche sont la direction. Si vous êtes à 1 1 à ce moment, alors +0 +1 devient 1 2, alors c'est la bonne, +1 +0 est 2 1 et descend un . Les quatre directions sont comme ça, si c'est huit directions, vous avez besoin de plus

int dx[] = {1,0,0,-1,1,-1,1,-1}
int dy[] = {0,1,-1,0,1,-1,-1,1}

La première étape est résolue, commençons la deuxième étape

Étape 2 : Trouvez le point de départ, les exigences du titre et démarrez le DFS

Par exemple, si on nous demande de trouver un bloc connexe, nous pouvons boucler tout le graphe, entrer deux fors, puis entrer la recherche si la position du graphe est égale au caractère ou au numéro dont le bloc connexe, le code est comme suit

for(int i=1;i<=n;i++)
{
    for(int j=1;j<=m;j++)
    {
        if(s[i][j]=='*')
        {
            dfs(i,j);
        }
    }
}

Vient ensuite notre troisième étape, l'écriture de la fonction dfs

Comment écrire la fonction dfs, marquez d'abord la position actuelle a été dépassée, puis écrivez une boucle, il y a plusieurs directions pour boucler plusieurs couches, écrivez dans la boucle pour juger si elle a franchi la limite et si elle répond aux exigences, sinon, continuez à récursif, le code est le suivant

bool pd(int x,int y)
{
	if(x<1||x>n||y<1||y>m)
	{
		return false;
	}
	if(vis[x][y])
	{
		return false;
	}
	return true;
}
void dfs(int x, int y)
{
    vis[x][y] = 1;
    for(int i=0;i<4;i++)
	{
		int xx = x+dx[i];
		int yy = y+dy[i];
        if(pd(xx,yy)&&s[xx][yy]=='.')
        {
        	dfs(x+xx[i],y+yy[i]);
		}
    }
}

La quatrième étape consiste à enregistrer la sortie de la réponse, ce qui est très simple, nous ne mettrons pas le code.

Pour résumer, nous avons appris un modèle de code pour le bloc Unicom dfs. Lorsque nous rencontrons le problème du bloc Unicom, nous pouvons utiliser ces quatre étapes pour le résoudre correctement. Jetons un coup d'œil et enregistrons d'abord ces quatre étapes, puis nous allons faites-en deux pour le consolider!

Exercice 1 : Batailles navales

Description du sujet

Pendant le sommet, les forces armées sont en état d'alerte maximale. La police surveillera chaque rue, l'armée gardera les bâtiments et l'espace aérien sera rempli d'avions F-2003. De plus, des croiseurs et des flottes seront envoyés pour protéger le littoral. Malheureusement, pour diverses raisons, l'Amirauté de la Défense n'a que quelques officiers capables de commander de grandes batailles navales. Ils ont donc envisagé de former de nouveaux commandants navals et ont choisi le jeu "Sea Battle" pour les aider dans leur apprentissage.

Dans ce célèbre jeu, un nombre et une forme fixes de navires sont placés sur une plaque carrée, chacun ne pouvant pas toucher les autres. Dans ce problème, on ne considère que les bateaux comme étant carrés, tous les bateaux sont des carrés composés de figures. Écrivez un programme pour trouver le nombre total de navires placés sur le plateau.

format d'entrée

La première ligne du fichier d'entrée est constituée de deux nombres entiers R et C séparés par des espaces, 1<=R, C<=1000, ces deux nombres représentent respectivement le nombre de lignes et de colonnes du plateau de jeu. Les lignes R suivantes contiennent chacune des caractères C, chacun pouvant être "#" ou ".", où "#" représente une partie d'un bateau et "." représente l'eau.

format de sortie

Sortez une ligne de la solution pour chaque paragraphe. Si la position des navires est correcte (c'est-à-dire qu'il n'y a que des cases sur le plateau qui ne peuvent pas se toucher, si deux signes "#" sont côte à côte en haut et en bas ou à gauche et à droite mais appartiennent à deux navires différents, les deux navires sont appelés contactés). Il suffit de sortir une phrase "Il y a S navires.", S représente le nombre de navires. Sinon, affichez "Mauvais placement.".

6 8
.....#.#
##.....#
##.....#
.......#
#......#
#..#...#

Ce qui précède est le problème le plus simple pour juger des blocs connectés. Nous appliquons directement la méthode en quatre étapes. La première étape consiste à enregistrer la carte, la direction et la marque.

Parce que le titre nécessite quatre directions, un tableau à deux chiffres, il suffit donc d'appuyer sur ce qui précède pour l'ouvrir.

Code:

#include<bits/stdc++.h>
using namespace std;
const int N = 1001;
int dx[] = {1,0,0,-1};
int dy[] = {0,1,-1,0};
char s[N][N];
bool vis[N][N];
int main()
{
	int r,c;
	cin>>r>>c;
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			cin>>s[i][j];
		}
	}
	return 0;
}

Ensuite, c'est notre deuxième étape, trouver le point de départ, les exigences du sujet et démarrer dfs

Le titre exige qu'il ne puisse y avoir de navires adjacents. La signification du titre est que s'il y a trois coques dans une grille 2*2, elle est adjacente, donc c'est faux. Vous devez écrire une fonction pour juger indépendamment. le point de départ est n'importe lequel rencontré.

bool pd(int a,int b)
{
	int sum = 0;
	if(s[a][b]=='#')
	{
		sum++;
	}
	if(s[a+1][b]=='#')
	{
		sum++;
	}
	if(s[a][b+1]=='#')
	{
		sum++;
	}
	if(s[a+1][b+1]=='#')
	{
		sum++;
	}
	if(sum==3)
	{
		return false;
	}
	return true;
}

C'est sous la fonction de jugement, dans les quatre directions du bas droit et du droit, de déterminer s'il y a une bombe.

Ensuite, il y a notre code pour trouver le point de départ

for(int i=1;i<=r;i++)
{
	for(int j=1;j<=c;j++)
	{
		if(s[i][j]=='#'&&vis[i][j]==0)
		{
			dfs(i,j);
		}
	}
}

Trouvez le numéro de coque et lancez une recherche.

Vient ensuite notre troisième étape, écrire dfs.

Comment écrire dfs, rappelez-vous ce que nous avons dit plus haut, traversez la frontière, marchez ou pas, faites du vélo.

bool yuejie(int x,int y)
{
	if(x<1||x>r||y<1||y>c)
	{
		return false;
	}
	if(vis[x][y])
	{
		return false;
	}
	return true;
}
void dfs(int x,int y)
{
	vis[x][y] = 1;
	for(int i=0;i<4;i++)
	{
		int xx = x+dx[i];
		int yy = y+dy[i];
		if(yuejie(xx,yy)&&s[xx][yy]=='#')
		{
			dfs(xx,yy);
		}
	}
}

La quatrième étape est notre réponse. Nous jugeons d'abord si le navire est bombardé, puis définissons une variable. Chaque fois que nous entrons dans le bloc China Unicom, ce sera +1. Si le bombardement du navire se termine directement, il n'est pas nécessaire juger.

Le code complet est le suivant

#include<bits/stdc++.h>
using namespace std;
const int N = 1001;
int dx[] = {1,0,0,-1};
int dy[] = {0,1,-1,0};
char s[N][N];
bool vis[N][N];
int r,c;
int num;
bool yuejie(int x,int y)
{
	if(x<1||x>r||y<1||y>c)
	{
		return false;
	}
	if(vis[x][y])
	{
		return false;
	}
	return true;
}
void dfs(int x,int y)
{
	vis[x][y] = 1;
	for(int i=0;i<4;i++)
	{
		int xx = x+dx[i];
		int yy = y+dy[i];
		if(yuejie(xx,yy)&&s[xx][yy]=='#')
		{
			dfs(xx,yy);
		}
	}
}
bool pd(int a,int b)
{
	int sum = 0;
	if(s[a][b]=='#')
	{
		sum++;
	}
	if(s[a+1][b]=='#')
	{
		sum++;
	}
	if(s[a][b+1]=='#')
	{
		sum++;
	}
	if(s[a+1][b+1]=='#')
	{
		sum++;
	}
	if(sum==3)
	{
		return false;
	}
	return true;
}
int main()
{
	cin>>r>>c;
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			cin>>s[i][j];
		}
	}
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			if(pd(i,j)==false)
			{
				cout<<"Bad placement.";
				return 0;
			}
		}
	}
	for(int i=1;i<=r;i++)
	{
		for(int j=1;j<=c;j++)
		{
			if(s[i][j]=='#'&&vis[i][j]==0)
			{
				num++;
				dfs(i,j);
			}
		}
	}
	printf("There are %d ships.",num);
	return 0;
}

Climatisation directe ! En fait, ce code peut être utilisé sans vis, de sorte que la quantité de code est plus petite.Vous pouvez penser à l'écrire vous-même.

ps : modifier la valeur de l'image d'origine

Si vous suivez, vous devez comprendre que si vous résolvez le bloc dfs de China Unicom, j'ai préparé quelques questions, vous devez me contacter, rappelez-vous ma méthode en quatre étapes et résolvez-la par vous-même, vous résoudrez un dfs vous-même. !

Luogu : P1451 Trouver le nombre de cellules - Luogu | Nouvelle écologie de l'enseignement de l'informatique (luogu.com.cn)

P1596 [USACO10OCT]Lake Counting S - Luogu | Nouvelle écologie de l'enseignement de l'informatique (luogu.com.cn)

Les questions ne sont pas difficiles, il suffit de les taper par vous-même !

Et puis il y a notre gamme complète.

La permutation complète est également une méthode en quatre étapes, voici le problème de permutation complète le plus classique à expliquer

Exercice 2 : Disposition

Description du sujet

Sort toutes les permutations non répétées des nombres naturels 1 à n dans l'ordre lexicographique, c'est-à-dire la permutation complète de n, exigeant qu'aucun nombre répété n'apparaisse dans une séquence de nombres générée.

format d'entrée

Un entier nn.

format de sortie

Toutes les séquences uniques de nombres composées de 1∼n, une séquence par ligne.

5 largeurs de champ sont réservées pour chaque numéro.

En voyant cette question, beaucoup de gens ont ri. Cette question est également très simple. Voici la méthode en quatre étapes.

La première étape, nous n'avons pas le tableau de direction, consiste à juger s'il a été utilisé et à stocker le tableau de valeurs.

int n,pd[100],a[100];

La deuxième étape, trouver le point de départ, les exigences du titre, démarrer dfs

Le point de départ est naturellement 0, puis la recherche directement.

int main()
{
    cin>>n;
    dfs(0);
    return 0;
}

La troisième étape, écrire la fonction dfs

L'exigence de la question est n, nous devons donc d'abord juger si l'exigence de la question est remplie, puis sortir et retourner, sinon, puis rechercher vers le bas, car la question nécessite n, donc la boucle se termine par = n, et chaque fois que nous jugeons si le numéro est utile ou non Cependant, si nous ne l'utilisons pas, nous le sauvegardons, puis écrivons une simple recherche mémorisée, car ce sera compliqué si nous ne nettoyons pas la scène lorsque nous revenons après utilisation.

Par exemple, si vous utilisez 123456, si vous ne revenez pas à 0, alors la boucle suivante jugera que votre tableau est toujours 123456, ce qui entraînera des erreurs de données.

void dfs(int k)
{
    if(k==n)
    {
        for(int i=1;i<=n;i++)
        {
            printf("%5d",a[i]);
        }
        printf("\n");
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!pd[i])
        {
            pd[i]=1;
            a[k+1]=i;
            dfs(k+1);
            pd[i]=0;
        }
    }
}

La quatrième étape est la nôtre ! Ha ha ha ha

Le code complet est le suivant

#include<bits/stdc++.h>
using namespace std;
int n,pd[100],a[100];
void dfs(int k)
{
    if(k==n)
    {
        for(int i=1;i<=n;i++)
        {
            printf("%5d",a[i]);
        }
        printf("\n");
        return ;
    }
    for(int i=1;i<=n;i++)
    {
        if(!pd[i])
        {
            pd[i]=1;
            a[k+1]=i;
            dfs(k+1);
            pd[i]=0;
        }
    }
}
int main()
{
    cin>>n;
    dfs(0);
    return 0;
}

Il y a encore deux questions pratiques ici. Vous pouvez vous entraîner vous-même après le cours et vous pourrez en maîtriser une !

Luogu : Sélection P1036 [Groupe de vulgarisation NOIP2002] - Luogu | Nouvelle écologie de l'enseignement de l'informatique (luogu.com.cn)

P1157 Sortie combinée - Luogu | Nouvelle écologie de l'enseignement de l'informatique (luogu.com.cn)

Résumer

Aujourd'hui, nous avons découvert le jugement de bloc de connexion et le jugement d'arrangement complet de dfs. Ceux-ci sont couramment utilisés. D'autres variantes nécessitent notre flexibilité. Comment écrire 4. L'arrangement complet de la sortie de réponse est : 1. Enregistrez la réponse pour juger 2. Le point de départ dfs 3. Comment écrire la fonction dfs 4. La sortie de réponse. Ces deux méthodes sont en fait similaires, c'est-à-dire que l'ensemble de l'arrangement n'a aucune direction, et plus est le jugement de savoir si le nombre est utilisé ou non. Tout le monde devrait le garder à l'esprit avant de pouvoir casser le dfs ! 

Je suppose que tu aimes

Origine blog.csdn.net/qq_45400861/article/details/124082034
conseillé
Classement