DFS(思路加简单例题)
dfs即深度优先搜索,就是只要我还能走,我就一条路走到头,直到我最后不能走的时候我再回头去找别的路。
深度优先搜索遍历连通图
1)从图中某个顶点出发,访问x,并置mp[x]的值为true.
2) 依次检查x的所有的邻接点w,如果mp[w]的值为false,再从w出发进行递归遍历,直至图中所有的顶点都被访问过。
/*
void dfs()
{
if(判断条件)
return ;
for(拓展状态)
{
判断合法
记录
dfs(继续搜);
回溯;
}
}
*/
一,走迷宫类型
题目描述
小明现在在玩一个游戏,游戏来到了教学关卡,迷宫是一个NM的矩阵.
小明的起点在地图中用“S”来表示,终点用“E”来表示,障碍物用“#”来表示,空地用“.”来表示。
障碍物不能通过。小明如果现在在点(x,y)处,那么下一步只能走到相邻的四个格子中的某一个:(x+1,y),(x-1,y),(x,y+1),(x,y-1);
小明想要知道,现在他能否从起点走到终点。
输入描述:
本题包含多组数据。
每组数据先输入两个数字N,M
接下来N行,每行M个字符,表示地图的状态。
数据范围:
2<=N,M<=500
保证有一个起点S,同时保证有一个终点E.
输出描述:
每组数据输出一行,如果小明能够从起点走到终点,那么输出Yes,否则输出No
示例1
输入
3 3
S..
..E
...
3 3
S##
###
##E
输出
Yes
No
#include<bits/stdc++.h>
using namespace std;
int n,m;
char a[505][505],mp[505][505];
int aa[4][2]={1,0,-1,0,0,1,0,-1};
int xx,yy,x,y;
void dfs(int i,int j)
{
if(i==x&&j==y)
return ;//找到出口,从递归出来
mp[i][j]=1;//标记走过的地方
for(int k=0;k<=3;k++)
{
int dx=i+aa[k][0];
int dy=j+aa[k][1];
if(a[dx][dy]!='#'&&dx>0&&dx<=n&&dy>0&&dy<=m&&!mp[dx][dy])//判断是否能走
{
mp[dx][dy]=1;
dfs(dx,dy);//继续走到下一步
}
}
}
int main()
{
while(cin>>n>>m)
{
int i,j;
memset(mp,0,sizeof(mp));
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
cin>>a[i][j];
if(a[i][j]=='S')//记录起点
xx=i,yy=j;
if(a[i][j]=='E')
x=i,y=j;//记录终点
}
}
dfs(xx,yy);
if(mp[x][y])
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}
二 ,选数,排列组合问题,暴力组合
题目描述
已知 n个整数 x1,x2,…, x n x_n xn 以及1个整数k(k<n)。从n个整数中任选k个整数相加,可分别得到一系列的和。例如当n=4,k=3,4个整数分别为3,7,12,19时,可得全部的组合与它们的和为:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29
输入格式
键盘输入,格式为:
n,k(1≤n≤20,k<n)
x1,x2,…, x n x_n xn(1≤xi≤5000000)
输出格式
屏幕输出,格式为: 1个整数(满足条件的种数)。
输入输出样例
输入 #1
4 3
3 7 12 19
输出 #1
1
#include<bits/stdc++.h>
using namespace std;
int a[10000],sum=0,ans=0;
int n,k;
int sushu(int f)
{
for(int i=2;i<=sqrt(f);i++)
{
if(f%i==0)
return 0;
}
return 1;
}
void dfs(int t,int x)//t表示还差多少个选到k个,x表示选到a【x】。
{
if(t==0)
ans+=sushu(sum);
else
{
x++;
for(int i=x;i<=n;i++)
{
sum+=a[i];
t--;
dfs(t,i);
sum-=a[i];//回溯
t++;
}
}
}
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;
}
三,连通性
题目描述
一矩形阵列由数字 0到 9组成,数字 1 到 9 代表细胞,细胞的定义为沿细胞数字上下左右若还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
输入格式
第一行两个整数代表矩阵大小 n和 m。
接下来 n行,每行一个长度为 m的只含字符 0
到 9
的字符串,代表这个 n×m 的矩阵。
输出格式
一行一个整数代表细胞个数。
输入输出样例
输入 #1
4 10
0234500067
1034560500
2045600671
0000000089
输出 #1
4
说明/提示
数据规模与约定
对于 100%的数据,保证 1≤n,m≤100。
#include<bits/stdc++.h>
using namespace std;
int n,m,ans=0;
int a[105][105];
bool mp[105][105];
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
void dfs(int x,int y)//查找与该点连通的点
{
mp[x][y]=1;
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(a[nx][ny]==0 || mp[nx][ny]==1) continue;
dfs(nx,ny);
}
}
int main()
{
cin>>n>>m;
memset(a,0,sizeof(a));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%1d",&a[i][j]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(mp[i][j]==0 && a[i][j]!=0)//找到未走过的不为0的数
{
dfs(i,j);//将与这个数连通的全都标记为走过即为1
ans++;
}
}
}
cout<<ans;
return 0;
}