【Codeforces Round #634 (Div. 3) 】F. Robots on a Grid

题目链接:https://codeforces.com/contest/1335/problem/F
题目大意:
机器人按轨道运行,在运行中机器人间不能发生冲撞。
问最多能摆放多少机器人,和在最大摆放的前提下能占据多少黑块。

个人思路:
找到每个连通块,在每个回路(根据题意所有回路一定是简单回路)上选一个点逆向进行BFS搜索,在同一层上被搜到的点中只要有一个黑块就说明机器人可以通过这个黑块无拥挤的进入回路,占据黑块的总量加一。

#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
#define pr pair<int,int>

using namespace std;
typedef long long ll;
const int N=2e6+5;
char ch;
int ans_a,ans_b,idx,n,m;
int vis[N],b[N],a[N],dfn[N],inque[N];
vector<int> c[N];
//b数组表示连出,c表示连入

void fill_(int p) {
    if(vis[p]) return ;
    vis[p]=1;
    fill_(b[p]);
    for(int v:c[p]) fill_(v);
}
//每次访问过一个连通块后标记

void bfs(int p,int mx) {
    queue<pr> que;
    que.push(pr(0,p));
    inque[p]=1;
    vector<int> ans(mx);
    while(!que.empty()) {
        pr t=que.front();que.pop();
        int u=t.second,cnt=t.first;
        if(!a[u]) ans[cnt%mx]=1;
        for(int v:c[u]) {
            if(!inque[v]) que.push(pr(cnt+1,v));
            inque[v]=1;
        }
    }
    ans_a+=mx;
    rep(i,mx) if(ans[i]) ans_b++;
}

void dfs(int p) {
    if(dfn[p]) {
        bfs(p,idx+1-dfn[p]);
        return ;
    }
    dfn[p]=++idx,dfs(b[p]);
}
//建立dfn序,idx+1-dfn即为环的大小


void solve() {
    cin>>n>>m;
    idx=ans_a=ans_b=0;
    rep(i,n*m) vis[i]=dfn[i]=inque[i]=0,c[i].clear();
    rep(i,n) rep(j,m) {
        int p=i*m+j;
        cin>>ch;
        a[p]=ch-'0';
    }
    rep(i,n) rep(j,m) {
        int p=i*m+j;
        cin>>ch;
        switch(ch) {
            case 'L':b[p]=p-1;c[p-1].push_back(p);break;
            case 'R':b[p]=p+1;c[p+1].push_back(p);break;
            case 'U':b[p]=p-m;c[p-m].push_back(p);break;
            case 'D':b[p]=p+m;c[p+m].push_back(p);
        }
    }
    rep(i,n) rep(j,m) {
        int p=i*m+j;
        if(!vis[p]) dfs(p);
        fill_(p);
    }
    cout<<ans_a<<' '<<ans_b<<'\n';
}

int main() {
    ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--) solve();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值