题目大意

给出一个 n×mn\times m 的网格,每个格子被染成黑色或白色,并且在每个格子上都有一个方向。你可以在一些格子中放置机器人,但要求所有的格子内的机器人均可以一直走走下去,一直不与其他机器人相撞。要求在满足上述条件的情况下使得机器人数量和机器人占据的黑格数量均最多。

思路

因为格子的数量是有限的,而机器人却需要重复无限次的行走,所以显然所有的机器人在最后都会汇聚到环上。因为整个图的可以行走的格子数量不会超过 n×mn\times m,所以在机器人行走 n×mn\times m 步之后,所有应该重复的机器人应该已经重合了。

所以我们假设所有的格子在一开始都有机器人,那么在走了 n×mn\times m 步之后,所有应该相遇的机器人应该已经全部相遇了。如果在最后有机器人相遇了,那么就说明这些格子只能放置一个机器人。因为需要将黑色格子放置的机器人最大化,那么如果有来自黑色格子的机器人,那么就将这个格子让给黑色格子的机器人。

因为要模拟 n×mn\times m 个机器人走 n×mn\times m 步,所以直接模拟会超时,需要考虑倍增。预处理出数组 ff,其中 fi,jf_{i,j} 表示编号为 ii 的机器人走 2j2^j 步到达的格子。

这样就可以快速的知道在 n×mn\times m 秒后的答案,时间复杂度为 O(nmlogn)O(nm\log n)

AC Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int t,n,m,c[N],f[N][22],cnt[N][2];
char a[N];
void solve(){
	cin>>n>>m;
	for(int i=0;i<n;i++){
		cin>>a;
		for(int j=0;j<m;j++) c[i*m+j]=a[j];
	}for(int i=0;i<n;i++){
		cin>>a;
		for(int j=0;j<m;j++){
			if(a[j]=='U') f[i*m+j][0]=(i-1)*m+j;
			if(a[j]=='D') f[i*m+j][0]=(i+1)*m+j;
			if(a[j]=='L') f[i*m+j][0]=i*m+j-1;
			if(a[j]=='R') f[i*m+j][0]=i*m+j+1;
		}
	}for(int i=0;i<n*m;i++) cnt[i][0]=cnt[i][1]=0;
	int p=log2(n*m)+1;
	for(int i=1;i<=p;i++){
		for(int j=0;j<n*m;j++){
			f[j][i]=f[f[j][i-1]][i-1];
		}
	}for(int i=0;i<n*m;i++){
		int k=f[i][p];
		if(c[i]==48) cnt[k][0]++;
		else cnt[k][1]++;
	}int ans1=0,ans2=0;
	for(int i=0;i<n*m;i++){
		if(cnt[i][0]||cnt[i][1]) ans1++;
		if(cnt[i][0]) ans2++;
	}cout<<ans1<<" "<<ans2<<endl;
}
signed main(){
	int T;cin>>T;
	while(T--) solve();
	return 0;
}