CF 1613E. Crazy Robot(拓扑)

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;
}

挺好的一道题。

猜你喜欢

转载自blog.csdn.net/Mr_dimple/article/details/121737701
今日推荐