1189 SEARCH
一、用普通深搜
这是洛谷唯一一个迭代加深的题目,真的是太少了,用它来练练手
这个问题的求解思路就是说按照它所给的方向进行一个搜索,而不是我们一贯的使用上下左右的顺序了,这就是我之前和zqc问的一样,分题而异,这个题就得按照所给方向
搜索函数,第一次从小偷位置开始,每次获取当前所在点的坐标,然后枚举所给的方向d,实现预备好方位数组,然后判度递归并且不能为’X‘,接着递归,坐标加上方位数组
这里的获取方位数组,比较巧妙,枚举四个方位到底是哪一个方向,然后返回0 1 2 3,根据这个在找到事先准备的方位数组
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};//枚举四个方向
int r,c;int n;
int sx,sy;
int b[65][65][1005];
char d[1005][15];
char a[65][65];
inline void read()
{
cin>>r>>c;
for(int i=1;i<=r;i++)
cin>>a[i]+1;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>d[i];
}
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
if(a[i][j]=='*')
{
sx=i;
sy=j;
break;
}
}
}
a[sx][sy]='.';
}
int go(char x)
{//判断方位
if(x == 'N')//上
return 2;
if(x == 'S')//下
return 0;
if(x == 'E')//左
return 1;
if(x == 'W')//右
return 3;
}
bool pd(int x,int y)
{//判断越界函数
return x<=r&&y<=c&&x>0&&y>0;
}
void dfs(int x,int y,int s)
{
if(b[x][y][s])
return ;
b[x][y][s]=1;
if(s==n+1)//边界
{
a[x][y]='*';
return ;
}
else
{
int ex=x,ey=y;
p=go(d[s][0]);
ex+=dx[p];
ey+=dy[p];
while(pd(ex,ey)&&a[ex][ey]!='X')
{
dfs(ex,ey,s+1);//递归方向
ex+=dx[p];
ey+=dy[p];
}
}
}
int main()
{
read();
dfs(sx,sy,1);//从小偷的位置出发
for(int i=1;i<=r;i++)
{
cout<<a[i]+1<<endl;
}
return 0;
}
二、用迭代加深搜索
题目大意我们都已经知道了,直接说思路了
迭代加深的思想:
1.先制定一个小目标,搜索的深度不超过1层,看看能不能搜到答案
2.如果不行,就把搜索深度设置为2,看能不能找到
3.如果不行,就把搜索深度设置为3,看能不能找到
直到设置成p,找到答案为止
个人理解的迭代加深就是枚举加上循环
经过3天的训练,终于把这道题 做出来了,真的是好棒。首先我先说明一下在写代码的时候,注意定义变量的时候map,ch这两个变量,因为这两个变量都在库存过,会起冲突了,因为这个我调了两个小时
首先我们定义一个数组a[i][j]表示(i,j)这个点由a[i][j]步到达,所以一开始的起点(*)就是a[i][j]=1,到达不了的点(X)就是a[i][j]=-1,其他的点就是a[i][j]=0
那么在这里运用的迭代加深的思想就很明显了,迭代是指的q步数,而加深就是说的移动,也就是上左下右的移动
迭代,所以我们一开始的时候输入时候将a数组初始化,然后枚举q个步数,接着判断是否到达了一个新的限制,进行重新搜索,枚举四个方向,上左下右(NSWE)的搜索直至搜索到了边界或者不能到达的点,就要停下来了,继续新的迭代搜索
加深,接下来的加深其实就没有运用到递归搜索这个算法,只是按着这个方向一直循环搜索,一直到边界或者不能到达的点(X),记得保存a数组的步数
最后就是输出,判断最后的步数,如果q+1步说明可以到达,输出即可
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
int q;
int a[65][65];//a[i][j]数组记录(i,j)位置由a[i][j]步到达
char cch[11];
char mapp[55][55];
bool pd(int x,int y)
{
return x>=0&&x<n&&y>=0&&y<m;
}
void shang(int x,int y,int id)
{
while(pd(x,y)&&mapp[x][y]!='X')
{
a[x][y]=id+1;
x--;//一直向上
}
}
void xia(int x,int y,int id)
{
while(pd(x,y)&&mapp[x][y]!='X')
{
a[x][y]=id+1;
x++;//一直向下
}
}
void zuo(int x,int y,int id)
{
while(pd(x,y)&&mapp[x][y]!='X')
{
a[x][y]=id+1;
y--;//一直向左
}
}
void you(int x,int y,int id)
{
while(pd(x,y)&&mapp[x][y]!='X')//循环模拟递归
{
a[x][y]=id+1;
y++;
}
}
void go(int id,char chh[])
{//迭代加深
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{//重复,重复 的过程不浪费时间吗?
if(a[i][j]==id)//到达搜索层
{
if(cch[0]=='N') shang(i-1,j,id);
else if(cch[0]=='S') xia(i+1,j,id);
else if(cch[0]=='W') zuo(i,j-1,id);
else you(i,j+1,id);
//模拟四个方向,加深搜索
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
cin>>mapp[i];
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mapp[i][j]=='X') a[i][j]=-1;//不能走
else if(mapp[i][j]=='*') a[i][j]=1;//起点一步到达
}
}
cin>>q;
for(int id=1;id<=q;id++)//将问题分解成q步
{
cin>>cch;//迭代加深p层搜索
go(id,cch);//限制搜索层数为id
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(mapp[i][j]=='X') cout<<'X';//到达死胡同
else if(a[i][j]==q+1) cout<<'*';//q步可以到达
else cout<<'.';
}
cout<<endl;
}
return 0;
}//自古忠孝难两全,金甲何许家团圆