Codeforces877 D. Olya and Energy Drinks(bfs+set)

题意:

在这里插入图片描述

解法:
直接bfs的复杂度是O(n*m*k),
但是如果我们能保证每个点都只被搜一次,那么就可以变成O(n*m).

可以用set存为访问过的节点,
这样的话,在bfs找后继的时候就不会访问已经走过的节点了,
总复杂度为O(n*m*log).
code:
#include<bits/stdc++.h>
#define PI pair<int,int>
using namespace std;
const int maxm=1e3+5;
set<int>R[maxm];
set<int>C[maxm];
char s[maxm][maxm];
int d[maxm][maxm];
PI st,ed;
int n,m,k;
void bfs(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            R[i].insert(j);
            C[j].insert(i);
        }
    }
    queue<PI>q;
    q.push(st);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            d[i][j]=-1;
        }
    }
    d[st.first][st.second]=0;
    R[st.first].erase(st.second);
    C[st.second].erase(st.first);
    while(q.size()){
        PI t=q.front();q.pop();
        int x=t.first,y=t.second;
        //
        R[x].insert(y);
        vector<int>temp;
        auto it=R[x].lower_bound(y);
        auto it2=it;
        while(1){
            it2++;
            if(it2==R[x].end())break;
            if(s[x][*it2]=='#')break;
            if(*it2-y>k)break;
            temp.push_back(*it2);
            d[x][*it2]=d[x][y]+1;
            q.push({x,*it2});
        }
        it2=it;
        while(1){
            if(it2==R[x].begin())break;
            it2--;
            if(s[x][*it2]=='#')break;
            if(y-*it2>k)break;
            temp.push_back(*it2);
            d[x][*it2]=d[x][y]+1;
            q.push({x,*it2});
        }
        R[x].erase(y);
        for(auto i:temp){
            R[x].erase(i);
            C[i].erase(x);
        }
        //
        temp.clear();
        C[y].insert(x);
        it=C[y].lower_bound(x);
        it2=it;
        while(1){
            it2++;
            if(it2==C[y].end())break;
            if(s[*it2][y]=='#')break;
            if(*it2-x>k)break;
            temp.push_back(*it2);
            d[*it2][y]=d[x][y]+1;
            q.push({*it2,y});
        }
        it2=it;
        while(1){
            if(it2==C[y].begin())break;
            it2--;
            if(s[*it2][y]=='#')break;
            if(x-*it2>k)break;
            temp.push_back(*it2);
            d[*it2][y]=d[x][y]+1;
            q.push({*it2,y});
        }
        C[y].erase(x);
        for(auto i:temp){
            R[i].erase(y);
            C[y].erase(i);
        }
    }
}
void solve(){
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++){
        cin>>(s[i]+1);
    }
    cin>>st.first>>st.second;
    cin>>ed.first>>ed.second;
    bfs();
    int ans=d[ed.first][ed.second];
    cout<<ans<<endl;
}
signed main(){
    ios::sync_with_stdio(0);cin.tie(0);
    solve();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值