Linking
大意:
一个机器人处在 n*m
的格子中的起点位置,最终要走到终点位置。
格子中有些位置可走,有些位置不可走。
每次可以给出一个指令往一个方向走一格,但机器人却会在其余三个方向中挑一个能走的前进。
问,有多少个位置可以作为起点,能够通过若干指令让机器人走到终点?
思路:
如果能够到达终点的话,说明从终点出发,能够前进到一个点。这个点最多只有两个方向可以走,选择以一个方向作为指令,那么机器人便会向另一方向走。便会走到走向终点的路上。如此往复。
但并不只有这一种情况。完全可能有多个方向可以走,但是无论走哪个方向都会到达终点。
所以,就需要像拓扑排序一样,每从一条路径到达了这个点,就把这个点的入度-1。
当从终点出发到达一个点的入度已经为1或者2了,说明除了这个来时的方向最多只有一个方向,这时候用另一方向作为指令,便会走到能够到达终点的点。
之后,该点入队,继续扩展。
Code:
const int N = 1000010, mod = 1e9+7;
int T, n, m;
map<PII,int> f,ru;
map<int,char> a[N];
int stx,sty;
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct node{
int x,y;
int frx,fry; //注意记录来时的点,防止重复跳转走。
};
void pre()
{
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
{
int cnt=0;
for(int d=0;d<4;d++)
{
int tx=i+dir[d][0],ty=j+dir[d][1];
if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]=='#') continue;
cnt++;
}
ru[{i,j}]=cnt;
}
}
}
void bfs()
{
f.clear();
queue<node> que;
que.push({stx,sty});
while(que.size())
{
int x=que.front().x, y=que.front().y;
int frx=que.front().frx,fry=que.front().fry;
que.pop();
for(int i=0;i<4;i++)
{
int tx=x+dir[i][0],ty=y+dir[i][1];
if(tx<1||tx>n||ty<1||ty>m||a[tx][ty]=='#'||a[tx][ty]=='+'||tx==frx&&ty==fry) continue;
ru[{tx,ty}]--;
if(ru[{tx,ty}]==1||ru[{tx,ty}]==0)
{
que.push({tx,ty,x,y});
if(a[tx][ty]=='.') a[tx][ty]='+';
}
}
}
}
int main(){
Ios;
cin>>T;
while(T--)
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>a[i][j];
if(a[i][j]=='L') stx=i,sty=j;
}
pre();
bfs();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cout<<a[i][j];
}
cout<<"\n";
}
}
return 0;
}
挺好的一道题。