目录
目录
深度优先搜索
基本概念
算法思想
模板
P1706 全排列问题
P1219 [USACO1.5]八皇后 Checker Challenge
P1605 迷宫
P1101 单词方阵
深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法。 沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过或者在搜寻时结点不满足条件,搜索将回溯到发现节点v的那条边的起始节点。整个进程反复进行直到所有节点都被访问为止。属于盲目搜索,最糟糕的情况算法时间复杂度为O(!n)。
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
void dfs(int step)
{
判断边界
{
相应操作
}
尝试每一种可能
{
满足check条件
标记
继续下一步dfs(step+1)
恢复初始状态(回溯的时候要用到)
}
}
#include
#include
int a[15];
int b[15];
int n;
void dfs(int);
int main()
{
scanf("%d",&n);
dfs(1);
return 0;
}
void dfs(int m)
{
int j;
if(m==n+1) //边界,输出
{
for(int i=1;i<=n;i++)
printf("%5d",a[i]);
printf("\n");
return ;
}
for(j=1;j<=n;j++) //相当于遍历寻找
{
if(b[j]==0)
{
a[m]=j;
b[j]=1;
dfs(m+1);
b[j]=0; //回溯
}
}
}
#include
int a[40];
int lie[40];
int u[40];
int v[40];
int n;
int cnt; //全局变量方便全局输入
void dfs(int);
int main()
{
scanf("%d",&n);
dfs(1);
printf("%d\n",cnt);
return 0;
}
void dfs(int x)
{
int i;
if(x==n+1) //边界,递归出口
{
cnt++;
if(cnt<=3) //输出前三行
{
for(i=1;i<=n;i++)
printf("%d ",a[i]);
printf("\n");
}
}
for(i=1;i<=n;i++) //遍历,从第一列到第n列,记住,x为行数
{
if(!lie[i] && !u[x-i+n] && !v[x+i]) //标记过的就不管,这三个式子用来衡量坐标关系
{
lie[i]=1;
u[x-i+n]=1;
v[x+i]=1; //标记
a[x]=i; //a数组用来记住x行的i列,方便输出
dfs(x+1); //接下来这个递归就是更进一步
lie[i]=0; //重新标记为0,回溯
u[x-i+n]=0;
v[x+i]=0;
}
}
}
#include
int n,m,t,kx,ky,fx,fy,cnt;
int vis[10][10]; //原地图的起点和出口标记
int mp[10][10]; //障碍物的地图标记
int xx[]={1,0,-1,0};
int yy[]={0,1,0,-1}; //横纵坐标的方向改变
void dfs(int,int);
int main()
{
int tempx,tempy;
scanf("%d %d %d",&n,&m,&t);
scanf("%d %d %d %d",&kx,&ky,&fx,&fy);
while(t--) //标记障碍物
{
scanf("%d %d",&tempx,&tempy);
mp[tempx][tempy]=1;
}
vis[kx][ky]=1; //起点
dfs(kx,ky);
printf("%d\n",cnt);
return 0;
}
void dfs(int x,int y)
{
int i,dx,dy;
if(x==fx && y==fy)
{
cnt++;return ;
}
for(i=0;i<4;i++)
{
dx=xx[i]+x;
dy=yy[i]+y;
if(dx>=1 && dx<=n && dy>=1 && dy<=m && !vis[dx][dy] &&!mp[dx][dy]) //判断
{
vis[dx][dy]=1;
dfs(dx,dy);
vis[dx][dy]=0;
}
}
}
给一n \times nn×n的字母方阵,内可能蕴含多个“yizhong
”单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着 88 个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用*
代替,以突出显示单词。例如:
输入:
8 输出:
qyizhong *yizhong
gydthkjy gy******
nwidghji n*i*****
orbzsfgz o**z****
hhgrhwth h***h***
zzzzzozo z****o**
iwdfrgng i*****n*
yyyygggg y******g
输入 #1复制
7 aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa aaaaaaa
输出 #1复制
******* ******* ******* ******* ******* ******* *******
输入 #2复制
8 qyizhong gydthkjy nwidghji orbzsfgz hhgrhwth zzzzzozo iwdfrgng yyyygggg
输出 #2复制
*yizhong gy****** n*i***** o**z**** h***h*** z****o** i*****n* y******g
#include
#include
#define maxn 110
int mp[maxn][maxn];
char vis[maxn][maxn];
int n;
int xx[]={1,1,1,0,0,-1,-1,-1};
int yy[]={-1,0,1,1,-1,0,1,-1}; //八个方向
char str[]="yizhong";
void dfs(int,int);
int main()
{
int i,j;
scanf("%d",&n);
getchar();
for(i=0;i=0 && dx=0 && dy