DFS Deep Optimization Search

DFS Deep Optimization Search

DFS-Algorithmus

Gedanke: Gehen Sie weiter, bis Sie eine Lösung finden oder nicht mehr weitermachen können

Es ähnelt der ersten Wurzeldurchquerung des Baumes. Schlagen Sie einfach nicht gegen die Südwand und schauen Sie nicht zurück

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

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

DFS-Durchquerungsdiagramm

1. Besuchen Sie ab v0 in der Abbildung v0.

2. Suchen Sie den ersten nicht besuchten benachbarten Punkt von v0 und besuchen Sie den Scheitelpunkt. Wiederholen Sie diesen Schritt mit diesem Scheitelpunkt als neuem Scheitelpunkt, bis der gerade besuchte Scheitelpunkt keine nicht besuchten benachbarten Punkte mehr hat.

3. Kehren Sie zu dem zuvor besuchten Scheitelpunkt zurück, der noch nicht besuchte benachbarte Punkte aufweist, und besuchen Sie weiterhin den nächsten nicht besuchten führenden Knoten dieses Scheitelpunkts.

4. Wiederholen Sie die Schritte 2 und 3, bis alle Scheitelpunkte besucht sind und die Suche endet.

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

v0
v2
v1
v3
v4
v5
v6

DFS-Fragetyp


Eins: Datentyp

Prime Ring Problem

Titel

Schließen Sie bei gegebener Zahl n die Zahlen 1 ~ n in einen Kreis ein. Voraussetzung: Die Summe zweier benachbarter Zahlen ist eine Primzahl.

0 <n <20

Ausgabe:

  • Die Richtung der Zahlen ist dieselbe (dieselbe im Uhrzeigersinn oder dieselbe gegen den Uhrzeigersinn), und die Anordnung wird nicht wiederholt
  • Wenn es nur eine Zahl gibt (n == 1), geben Sie 1 aus
  • Ausgabefall k: (k ist die Anzahl der Datengruppen), jede Ausgabegruppe (mit Ausnahme der ersten) hat zuvor eine Leerzeile

Ideen

Beurteilen Sie vor jeder Rekursion, ob die Summe der ersten beiden Zahlen eine Primzahl ist, da es sich um einen Ring handelt, müssen auch die letzte Zahl und die erste Zahl erfüllt sein

Vor der DFS können Sie Primzahlen zum Sieben verwenden, Primzahlen innerhalb von 50 finden, wobei n 20 ist und die Summe der beiden größten Primzahlen weniger als 50 beträgt

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

Titelbeschreibung: Wählen Sie die Nummer

Bekannte n ganze Zahlen x1, x2, ..., xn x_n x ** n und 1 ganze Zahl k (k <n). Aus n ganzen Zahlen werden optional k ganze Zahlen addiert, um jeweils eine Reihe von Summen zu erhalten. Wenn beispielsweise n = 4, k = 3 und 4 ganze Zahlen 3, 7, 12, 19 sind, sind alle Kombinationen und ihre Summe:

3 + 7 + 12 = 22

3 + 7 + 19 = 29

7 + 12 + 19 = 38

3 + 12 + 19 = 34

Nun müssen Sie berechnen, wie viele Arten von Summen Primzahlen sind.

Im obigen Beispiel ist beispielsweise nur eine Art von Summe eine Primzahl: 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;
}

Zwei: Grafik

Pfad in der Matrix

Bitte entwerfen Sie eine Funktion, um zu beurteilen, ob es einen Pfad gibt, der alle Zeichen einer Zeichenfolge in einer Matrix enthält.

Der Pfad kann von einem beliebigen Raster in der Matrix aus beginnen, und jeder Schritt kann ein Raster in der Matrix nach links, rechts, oben und unten verschieben.

Wenn ein Pfad durch ein bestimmtes Gitter in der Matrix verläuft, kann er dieses Gitter danach nicht mehr eingeben.

Hinweis:

  • Der eingegebene Pfad ist nicht leer.
  • Alle angezeigten Zeichen sind englische Großbuchstaben

Stichprobe

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

Aus dem Labyrinth

Xiao Ming spielt gerade ein Spiel und das Labyrinth ist eine N * M-Matrix.

Der Startpunkt von Xiao Ming wird auf der Karte durch "S" dargestellt, der Endpunkt wird durch "E" dargestellt, Hindernisse werden durch "#" dargestellt und offene Räume werden durch "." Dargestellt.

Hindernisse können nicht passieren. Befindet sich Xiao Ming jetzt am Punkt (x, y), kann der nächste Schritt nur zu einem der vier benachbarten Gitter gehen: (x + 1, y), (x-1, y), (x, y +1), (x, y-1);

Xiao Ming möchte wissen, ob er jetzt von Anfang bis Ende gehen kann

Beispieleingabe
3 3
S..
..E
...
3 3
S##
###
##E
Beispielausgabe
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;
}

Ich denke du magst

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