[codeforces 1335F] Robots on a Grid 倍增

Codeforces Round #634 (Div. 3)   比赛人数11922  慢慢的对Div. 3难度有了些感觉

[codeforces 1335F]   Robots on a Grid   倍增

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1335/problem/F

ProblemLangVerdictTimeMemory
F - Robots on a Grid GNU C++17Accepted686 ms106600 KB

思路同https://blog.csdn.net/qq_45458915/article/details/105515708?fps=1&locationNum=2

假如两个机器人会冲突的话,也就是说在某个时刻,某个格子中同时出现了两个机器人,那么在接下来的移动过程中,显然这两个机器人的路径将保持一致,我们可以先假设 n * m 个格子中初始时都有一个机器人,先让这些机器人运动 n * m 秒,甚至更多,因为 n * m 的一个矩阵,最大可以形成的一个首尾相接的环路长度就是 n * m ,所以先让所有机器人都运动 n * m 秒后,该重合的机器人都已经重合了,并且不难统计每个位置中有多少个来自黑格的机器人,此时矩阵中仍然有机器人的地方,就说明这个位置是首尾相接的环,那么ans1++,如果这个地方至少有一个来自黑格的机器人,那就说明来到这个位置的机器人初始时可以摆在黑格上,即ans2++

实现的话肯定不是暴力模拟 n * m 秒,可以利用倍增,首先将 n * m 个格子按照 0 ~ n * m - 1 编号,那么 dp[ i ][ j ] 就代表编号为 i 的点走 2^j 步可以到达的地方,这里类比于树上倍增就好,剩下的实现起来就比较简单了


倍增数据理解如下

RL
dp[0][0]=1 dp[1][0]=0 
dp[0][1]=0 dp[1][1]=1 
dp[0][2]=0 dp[1][2]=1 

RLL
DLD
ULL
dp[0][0]=1 dp[1][0]=0 dp[2][0]=1 dp[3][0]=6 dp[4][0]=3 dp[5][0]=8 dp[6][0]=3 dp[7][0]=6 dp[8][0]=7 
dp[0][1]=0 dp[1][1]=1 dp[2][1]=0 dp[3][1]=3 dp[4][1]=6 dp[5][1]=7 dp[6][1]=6 dp[7][1]=3 dp[8][1]=6 
dp[0][2]=0 dp[1][2]=1 dp[2][2]=0 dp[3][2]=3 dp[4][2]=6 dp[5][2]=3 dp[6][2]=6 dp[7][2]=3 dp[8][2]=6 
dp[0][3]=0 dp[1][3]=1 dp[2][3]=0 dp[3][3]=3 dp[4][3]=6 dp[5][3]=3 dp[6][3]=6 dp[7][3]=3 dp[8][3]=6 
dp[0][4]=0 dp[1][4]=1 dp[2][4]=0 dp[3][4]=3 dp[4][4]=6 dp[5][4]=3 dp[6][4]=6 dp[7][4]=3 dp[8][4]=6 

RRD
RLD
ULL
dp[0][0]=1 dp[1][0]=2 dp[2][0]=5 dp[3][0]=4 dp[4][0]=3 dp[5][0]=8 dp[6][0]=3 dp[7][0]=6 dp[8][0]=7 
dp[0][1]=2 dp[1][1]=5 dp[2][1]=8 dp[3][1]=3 dp[4][1]=4 dp[5][1]=7 dp[6][1]=4 dp[7][1]=3 dp[8][1]=6 
dp[0][2]=8 dp[1][2]=7 dp[2][2]=6 dp[3][2]=3 dp[4][2]=4 dp[5][2]=3 dp[6][2]=4 dp[7][2]=3 dp[8][2]=4 
dp[0][3]=4 dp[1][3]=3 dp[2][3]=4 dp[3][3]=3 dp[4][3]=4 dp[5][3]=3 dp[6][3]=4 dp[7][3]=3 dp[8][3]=4 
dp[0][4]=4 dp[1][4]=3 dp[2][4]=4 dp[3][4]=3 dp[4][4]=4 dp[5][4]=3 dp[6][4]=4 dp[7][4]=3 dp[8][4]=4 

AC代码如下

#include <stdio.h>
#include <string.h>
#include <math.h>
#define maxn 1000010
int col[maxn],dir[maxn],dp[maxn][23],next[4][2]={-1,0,1,0,0,-1,0,1};//U,D,L,R
char buf[maxn];
int n,m,num[maxn][2];
int loc(int x,int y){
	return x*m+y;
}
int c2i(char c){
	if(c=='U')return 0;
	if(c=='D')return 1;
	if(c=='L')return 2;
	if(c=='R')return 3;
}
int main(){
	int t,i,j,limit,nm,k,ans1,ans2;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		nm=n*m,ans1=0,ans2=0;
		for(i=0;i<nm;i++)num[i][0]=num[i][1]=0;//初始化
		limit=log2(nm)+1;//倍增使用
		for(i=0;i<n;i++){
			scanf("%s",buf);
			for(j=0;j<m;j++)
				col[loc(i,j)]=buf[j]-'0';
		}
		for(i=0;i<n;i++){
			scanf("%s",buf);
			for(j=0;j<m;j++)
				dir[loc(i,j)]=c2i(buf[j]);
		}
		nm=n*m;
		for(i=0;i<n;i++)
			for(j=0;j<m;j++){
				k=dir[loc(i,j)];
				dp[loc(i,j)][0]=loc(i+next[k][0],j+next[k][1]);//初始化,第2^0=1步
			}
		for(j=1;j<=limit;j++)//倍增
			for(i=0;i<nm;i++)
				dp[i][j]=dp[dp[i][j-1]][j-1];
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)
				num[dp[loc(i,j)][limit]][col[loc(i,j)]]++;
		for(i=0;i<nm;i++){
			ans1+=!!(num[i][0]+num[i][1]);
			ans2+=!!num[i][0];
		}
		printf("%d %d\n",ans1,ans2);
	}
	return 0;
}

 

弄明白了,ID之前*的意义,注意,不是指该ID是作弊者,而是指,该ID此次的提交,在比赛中AC,并且因此Out of competition.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值