首页 > 其他 > 详细

[CF1335F] Robots on a Grid - 倍增

时间:2020-11-13 23:13:19      阅读:42      评论:0      收藏:0      [点我收藏+]

Description

给定 \(n \times m\) 的棋盘,每个格子有一个颜色和方向。如果一个机器人此时在某个格子中,那么下一时刻他会移动的这个格子的方向所指向的相邻的格子中。若干个机器人在棋盘上无限地走下去,请找出一种放置机器人的方案,需要保证任意时刻不会有两个机器人同时出现在同一个格子中,在最大化机器人总数的前提下,最大化初态下位于黑色格子上的机器人总数。

Solution

很显然我们需要对每一个“连通块”分别考虑,这个连通块一定包含一个环以及若干个内向链。

暴力找环用并查集维护当然可以,但是有点麻烦。

考虑到在足够长的时间后,所有机器人一定都会走到环上去,因此我们只需要给出一个足够大的 \(M\),求出 \(M\) 时间后,每个初态位置可以到达的位置,这些位置的并集的大小就是答案。

考虑倍增,令 \(f[i][j]\) 表示点 \(i\) 走了 \(2^j\) 步后的位置,常规处理即可。

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1000005;

int n,m,f[N][22],buc[N];
char col[N],dir[N];

void solve()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>col+(i-1)*m+1;
    for(int i=1;i<=n;i++) cin>>dir+(i-1)*m+1;
    for(int i=1;i<=n*m;i++) 
    {
        if(dir[i]==‘U‘) f[i][0]=i-m;
        if(dir[i]==‘D‘) f[i][0]=i+m;
        if(dir[i]==‘L‘) f[i][0]=i-1;
        if(dir[i]==‘R‘) f[i][0]=i+1;
    }
    for(int j=1;j<=20;j++) for(int i=1;i<=n*m;i++) 
    {
        f[i][j]=f[f[i][j-1]][j-1];
    }
    for(int i=1;i<=n*m;i++) buc[i]=0;
    for(int i=1;i<=n*m;i++) buc[f[i][20]]=1;
    int ans=0,ans2=0;
    for(int i=1;i<=n*m;i++) if(buc[i]) ans++;
    for(int i=1;i<=n*m;i++) buc[i]=0;
    for(int i=1;i<=n*m;i++) if(col[i]==‘0‘) buc[f[i][20]]=1;
    for(int i=1;i<=n*m;i++) if(buc[i]) ans2++;
    cout<<ans<<" "<<ans2<<endl;
}

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
}

[CF1335F] Robots on a Grid - 倍增

原文:https://www.cnblogs.com/mollnn/p/13971698.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!