分析:在一个图中只要看到D点和E点就行的最小步数,看到的定义是:也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。
所以可以先预处理地图,把D点和E点所在的行列的‘ .’扩展为d和e,然后只要搜到d和e就可以,问题是只有d和e同时搜到才行,直接广搜肯定不行,我们可以在搜到d点之后然后在从当前点广搜e点,或者e点广搜d点,这样第一次搜到的点不一定是最优的,所以需要枚举所有情况才行,时间复杂度较高。
比较好的一种方法是BFS+状态压缩,定义dp【i】【j】【st】:如果搜到e,状态变化dp【i】【j】【01】,重新初始化图标记,再搜,然后搜到d则dp【i】【j】【10】,知道dp【i】【j】【11】是step就是最小的。这样复杂度较低
BFS+状态压缩
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define INT long long
#define Del(a,b) memset(a,b,sizeof(a))
const INT inf = 0x3f3f3f3f;
const int N = 120;
int mp[N][N];
bool vis[N][N][4];
int n,m,t;
int ans;
struct Node
{
int x,y;
int step,st;
};
int dx[5]= {0,0,1,-1};
int dy[5]= {1,-1,0,0};
bool check(int x,int y)
{
if(mp[x][y]=='X' || mp[x][y]=='D' || mp[x][y]=='E')
return false;
return true;
}
char solve(char x,int ok)
{
if(ok && x=='e' || !ok && x=='d')
return 'y';
return ok?'d':'e';
}
void isit(int x,int y,int ok)
{
for(int i=x+1; i<m && check(i,y); i++)
mp[i][y]=solve(mp[i][y],ok);
for(int i=x-1; i>=0 && check(i,y); i--)
mp[i][y] = solve(mp[i][y],ok);
for(int j=y+1; j<n && check(x,j); j++)
mp[x][j] = solve(mp[x][j],ok);
for(int j=y-1; j>=0 && check(x,j); j--)
mp[x][j] = solve(mp[x][j],ok);
}
int ST_solve(char x,int st)
{
if(x=='d')
st|=1;
else if(x=='e')
st|=2;
else if(x=='y')
st|=3;
return st;
}
void BFS(Node s)
{
s.step = 0;
s.st = ST_solve(mp[s.x][s.y],0);
Del(vis,0);
queue<Node> q;
q.push(s);
vis[s.x][s.y][s.st]=1;
while(!q.empty())
{
Node x = q.front(),f;
q.pop();
if(x.st==3)
{
ans = x.step;
return ;
}
for(int i=0; i<4; i++)
{
f.x = x.x + dx[i];
f.y = x.y + dy[i];
f.step = x.step + 1;
f.st = x.st;
if(check(f.x,f.y) && vis[f.x][f.y][f.st]==0 && f.x>=0 && f.y>=0 && f.x<n && f.y<m)
{
f.st = ST_solve(mp[f.x][f.y],f.st);
vis[f.x][f.y][f.st]=1;
q.push(f);
}
}
}
}
int main()
{
int cas=1;
while(~scanf("%d%d%d",&n,&m,&t))
{
Del(mp,0); //记得初始化
Node s;
for(int i=0; i<n; i++)
{
getchar();
for(int j=0; j<m; j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='S')
s.x=i,s.y=j;
}
}
for(int i=0; i<n; i++) //预处理
{
for(int j=0; j<m; j++)
{
if(mp[i][j]=='D')
isit(i,j,1);
else if(mp[i][j]=='E')
isit(i,j,0);
}
}
ans = inf;
BFS(s);
printf("Case %d:\n",cas++);
if(ans<=t)
printf("%d\n",ans);
else
puts("-1");
}
return 0;
}
双广搜AC代码:
#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
#define INT long long
#define Del(a,b) memset(a,b,sizeof(a))
const INT inf = 0x3f3f3f3f;
const int N = 120;
int mp[N][N];
bool vis[N][N],css[N][N];
int n,m,t;
int ans; //标记
struct Node
{
int x,y;
int step;
};
int dx[5]= {0,0,1,-1};
int dy[5]= {1,-1,0,0};
bool check(int x,int y)
{
if(mp[x][y]=='X' || mp[x][y]=='D' || mp[x][y]=='E')
return false;
return true;
}
char solve(char x,int ok)
{
if(ok && x=='e' || !ok && x=='d')
return 'y';
return ok?'d':'e';
}
void isit(int x,int y,int ok)
{
for(int i=x+1; i<m && check(i,y); i++)
mp[i][y]=solve(mp[i][y],ok);
for(int i=x-1; i>=0 && check(i,y); i--)
mp[i][y] = solve(mp[i][y],ok);
for(int j=y+1; j<n && check(x,j); j++)
mp[x][j] = solve(mp[x][j],ok);
for(int j=y-1; j>=0 && check(x,j); j--)
mp[x][j] = solve(mp[x][j],ok);
}
int BFS2(Node s,int ok)
{
Del(css,0);
queue<Node> f;
f.push(s);
css[s.x][s.y]=1;
while(!f.empty())
{
Node x = f.front(),tmp;
f.pop();
if(ok && mp[x.x][x.y]=='e' || !ok && mp[x.x][x.y]=='d')
return x.step;
for(int i=0;i<4;i++)
{
tmp.x = x.x + dx[i];
tmp.y = x.y + dy[i];
tmp.step = x.step + 1;
if(check(tmp.x,tmp.y) && css[tmp.x][tmp.y]==0 && tmp.x>=0 && tmp.y>=0 && tmp.x<n && tmp.y<m)
{
css[tmp.x][tmp.y]=1;
f.push(tmp);
}
}
}
return inf;
}
void BFS(Node s)
{
s.step = 0;
Del(vis,0);
queue<Node> q;
q.push(s);
vis[s.x][s.y]=1;
while(!q.empty())
{
Node x = q.front(),f;
q.pop();
if(mp[x.x][x.y]=='y')
ans = min(ans,x.step);
else if(mp[x.x][x.y]=='d'){
int fff = BFS2(x,1);
ans = min(ans,fff);
}
else if(mp[x.x][x.y]=='e')
{
int eee = BFS2(x,0);
ans = min(ans,eee);
}
for(int i=0; i<4; i++)
{
f.x = x.x + dx[i];
f.y = x.y + dy[i];
f.step = x.step + 1;
if(check(f.x,f.y) && vis[f.x][f.y]==0 && f.x>=0 && f.y>=0 && f.x<n && f.y<m)
{
vis[f.x][f.y]=1;
q.push(f);
}
}
}
}
int main()
{
int cas=1;
while(~scanf("%d%d%d",&n,&m,&t))
{
Del(mp,0); //记得初始化
Node s;
for(int i=0; i<n; i++)
{
getchar();
for(int j=0; j<m; j++)
{
scanf("%c",&mp[i][j]);
if(mp[i][j]=='S')
s.x=i,s.y=j;
}
}
for(int i=0; i<n; i++) //预处理
{
for(int j=0; j<m; j++)
{
if(mp[i][j]=='D')
isit(i,j,1);
else if(mp[i][j]=='E')
isit(i,j,0);
}
}
ans = inf;
BFS(s);
printf("Case %d:\n",cas++);
if(ans<=t)
printf("%d\n",ans);
else
puts("-1");
}
return 0;
}