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