题解 P2864 【[USACO06JAN]The Grove S】
这个是建墙法。就是建一座墙,然后bfs。就变成了从出发点到墙,再从墙到出发点的问题。
代码:
#include<bits/stdc++.h>
using namespace std;
const int dx[8]={-1,1,0,0,-1,-1,1,1};
const int dy[8]={0,0,-1,1,-1,1,-1,1};
struct node
{
int x,y,k;
node(int a,int b,int c):x(a),y(b),k(c)
{
}
node(){
}
friend bool operator <(node a,node b)
{
return a.k > b.k;
}
};
priority_queue<node>q;
char mp[55][55];
bool vis[55][55];
int r,c;
int gx,gy,tx,ty,d[55][55][2];
bool across(node a,node b)//判断是否穿过墙
{
if(gx == a.x && gy > a.y && gx > b.x)
{
return 1;
}
if(gx == b.x && gy > b.y && gx > a.x)
{
return 1;
}
return 0;
}
void bfs()//广搜
{
while(q.size())
{
node bei = q.top(),yong;
q.pop();
int x = bei.x;
int y = bei.y;
int k = bei.k;
for(int i = 0; i < 8; i++)
{
int xx = dx[i] + x;
int yy = dy[i] + y;
yong = node(xx,yy,k);
if(xx < 0 || xx >= r || yy < 0 || yy >= c || vis[xx][yy] == 1)
{
continue;
}
if(across(bei,yong))
yong.k ^= 1;
if(d[yong.x][yong.y][yong.k] <= d[bei.x][bei.y][bei.k] + 1)
{
continue;
}
d[yong.x][yong.y][yong.k] = d[bei.x][bei.y][bei.k] + 1;
q.push(yong);
}
}
}
int main()
{
freopen("grove.in","r",stdin);
freopen("grove.out","w",stdout);
scanf("%d%d",&r,&c);
memset(d,0x7f,sizeof(d));
for(int i = 0; i < r; i++)
{
scanf("%s",mp[i]);
for(int j = 0; j < c; j++)
{
if(mp[i][j] == 'X')//建墙
{
vis[i][j] = 1;
if(!gy)
{
gx = i,gy = j;
}
}
else if(mp[i][j] == '*')//出发点
{
tx = i,ty = j;
d[i][j][0] = 0;
q.push(node(i,j,0));
}
}
}
bfs();//开始广搜
printf("%d",d[tx][ty][1]);//输出答案
return 0;
}