搜索
分为深度优先搜索DFS(Deep First Search)和广度优先搜索BFS(Breath First Search),重点在于剪枝,适用于因为条件过多而难以正常处理的环境,编码时需要大量的检验点来保障准确性
DFS
深度优先搜索适合判断能不能到某一个地方,特点是状态回溯和剪枝,在有多少种方法和能否判断上比BFS有优势
洛谷 P1784 数独
#include<bits/stdc++.h>
using namespace std;
#define foo(i,a,b) for(int i=a;i<b;i++)
#define fio(i,a,b) for(int i=a;i>b;i--)
const int N=11;
bool check[N][N],b[N][N],c[N][N],d[N][N]; //b指第i行j出没出现过,c指的是列,d值得是块
int a[N][N];
int reflect(int x,int y)
{
return (x-1)/3*3+(y-1)/3+1;//判断分区
}
void print(void)
{
foo(i,1,10)
{
foo(j,1,10)
{
cout<<a[i][j]<<" ";
}
cout<<"\n";
}
cout<<"\n";
}
void dfs(int x,int y)//这里用bfs要比dfs慢,因为bfs遍历的比dfs多
{
if(check[x][y])//判断有没有被填过
{
if(x==9&&y==9)
{
print();
return;
}
if(y==9)
{
dfs(x+1,1);
return;
}
else
{
dfs(x,y+1);
return;
}
}
foo(i,1,10)//这里从1到9不会有重合的可能,不需要剪枝
{
if(!b[x][i]&&!c[y][i]&&!d[reflect(x,y)][i])
{
a[x][y]=i;//猜测
b[x][i]=1,c[y][i]=1,d[reflect(x,y)][i]=1;
if(x==9&&y==9)print();
else if(y==9)dfs(x+1,1);
else dfs(x,y+1);
a[x][y]=0;//猜测失败,状态回溯
b[x][i]=0,c[y][i]=0,d[reflect(x,y)][i]=0;
}
}
}
signed main()
{
ios::sync_with_stdio(0);
foo(i,1,10)
{
foo(j,1,10)
{
cin>>a[i][j];
if(a[i][j])
{
b[i][a[i][j]]=1;
c[j][a[i][j]]=1;
d[reflect(i,j)][a[i][j]]=1;
check[i][j]=1;
}
}
}
dfs(1,1);
return 0;
}
洛谷 Phillip and Trains
#include<bits/stdc++.h>
using namespace std;
#define foo(i,a,b) for(int i=a;i<b;i++)
#define fio(i,a,b) for(int i=a;i>b;i--)
const int N=105;
int t,n,k;
bool a[4][N],flag;
void dfs(int x,int y)//用dfs因为找能不能出去,而不是最短几步出去,在这种条件下dfs优于bfs
{
if(y>=n&&flag==false)
{
cout<<"YES"<<endl;
flag=true;
return;
}
if(flag)return;
if(!a[x][y+1])
{
if(x+1<3&&!a[x+1][y+1]&&!a[x+1][y+2]&&!a[x+1][y+3])
{
dfs(x+1,y+3);
}
if(!a[x][y+2]&&!a[x][y+3])
{
dfs(x,y+3);
}
if(x-1>=0&&!a[x-1][y+1]&&!a[x-1][y+2]&&!a[x-1][y+3])
{
dfs(x-1,y+3);
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin>>t;
int nback=0;
char a_;
int x,y;
while(t--)
{
flag=false;
cin>>n>>k;
nback=n;
foo(i,0,3)
{
foo(j,0,n)
{
cin>>a_;
if(a_=='s')x=i,y=j;
else if(a_=='.') ;
else a[i][j]=1;
}
}
dfs(x,y);
if(!flag)cout<<"NO"<<endl;
memset(a,0,sizeof(a));
}
return 0;
}
BFS
广搜的数据记录一般用队列的形式,剪枝用数组,map函数容易爆,在最小步数问题中搜索算法只能用bfs
洛谷 P1379 八数码难题
#include<bits/stdc++.h>
using namespace std;
#define foo(i,a,b) for(int i=a;i<b;i++)
#define fio(i,a,b) for(int i=a;i>b;i--)
const int N=130;
struct A
{
int a[3][3];
int x,y;
int steps;
};
int b[3][3];
bool check(A B)
{
foo(i,0,3)
{
foo(j,0,3)
{
if(B.a[i][j]!=b[i][j])
{
return false;
}
}
}
return true;
}
int c[]={1,0,-1,0};
int d[]={0,1,0,-1};
string m="123804765";
signed main()
{
ios::sync_with_stdio(0);
A tempa,tt;
foo(i,0,3)foo(j,0,3)tempa.a[i][j]=int(m[i*3+j])-int('0');
tempa.x=1,tempa.y=1,tempa.steps=0;
cin>>m;
foo(i,0,3)
{
foo(j,0,3)
{
b[i][j]=int(m[i*3+j])-int('0');
}
}
queue<A> q;
q.push(tempa);
while(!q.empty())
{
tempa=q.front();
if(check(tempa))
{
cout<<tempa.steps;
break;
}
q.pop();
foo(i,0,4)
{
tt=tempa;
tt.steps++;
if(tt.x+c[i]<3&&tt.x+c[i]>=0&&tt.y+d[i]<3&&tt.y+d[i]>=0)
{
swap(tt.a[tt.x][tt.y],tt.a[tt.x+c[i]][tt.y+d[i]]);
tt.x+=c[i];
tt.y+=d[i];
if(check(tt))
{
cout<<tempa.steps+1;
exit(0);//表示正常退出代码
}
q.push(tt);
swap(tt.a[tt.x][tt.y],tt.a[tt.x-c[i]][tt.y-d[i]]);
}
}
}
return 0;
}
洛谷 P1443 马的遍历
#include<bits/stdc++.h>
using namespace std;
#define foo(i,a,b) for(int i=a;i<b;i++)
#define fio(i,a,b) for(int i=a;i>b;i--)
#define mp make_pair
const int N=500;
int n,m,x,y;
int a[N][N];
bool b[N][N];//这里的剪枝是这道题的关键
int op[][2]={{-2,-1},{-2,1},{-1,-2},{-1,2},{2,-1},{2,1},{1,2},{1,-2}};
struct biao
{
int x,y;
int cnt;
};
signed main()
{
scanf("%d%d%d%d",&n,&m,&x,&y);
foo(i,1,n+1)
{
foo(j,1,m+1)
{
a[i][j]=-1;
}
}
queue<biao> q;
biao temp;
temp.x=x;
temp.y=y;
temp.cnt=0;
q.push(temp);
a[x][y]=temp.cnt;
b[x][y]=1;
int tempx,tempy,cnt;
while(!q.empty())
{
tempx=q.front().x,tempy=q.front().y,cnt=q.front().cnt;
q.pop();
foo(i,0,8)
{
if(tempx+op[i][0]>=1&&tempx+op[i][0]<=n&&tempy+op[i][1]>=1&&tempy+op[i][1]<=m&&!b[tempx+op[i][0]][tempy+op[i][1]])//注意这里是一和零
{
temp.x=tempx+op[i][0],temp.y=tempy+op[i][1],temp.cnt=cnt+1;
q.push(temp);
a[temp.x][temp.y]=temp.cnt;
b[temp.x][temp.y]=1;
}
}
}
foo(i,1,n+1)
{
foo(j,1,m+1)
{
printf("%-5d",a[i][j]);
}
printf("\n");
}
return 0;
}