Olya and Energy Drinks分析

40 阅读2分钟

 题目链接
Olya and Energy Drinks - CodeForces 877D - Virtual Judge​​​​​​https://vjudge.net/problem/CodeForces-877Dhttps://vjudge.net/problem/CodeForces-877Dhttps://vjudge.net/problem/CodeForces-877D

常规思路分析:

使用BFS寻找最短路径,但是如果搜索到每个点的时候,对其上下左右分别进行k次新坐标的计算,再对每个计算出的新坐标进行判断有没有访问过的话,

时间复杂度可以达到:kmn,即1e9数量级,会超过时间

优化策略:

用集合(STL set)保存第i行还有哪些点没有被访问,用集合保存第j列还有哪些点没有被访问

在来到点(x,y)时,对于上下左右四个方向中的某一个,寻找,离这个点最近的点,然后将找到的点设置为新的基准点,再寻找在当前方向上,离这个基准点最近的新点,再将新点设置为基准点,如此反复,直到距离与(x,y)超过k或者是该点有垃圾

此时的复杂度为:mn*log(n)(每次找一个新点需要log(n)的复杂度,一共有mn个点)

#include<iostream>
#include<cstdio>
#include<queue>
#include<utility>
#include<set>
using namespace std;

const int maxn=1005;

int mp[maxn][maxn],vis[maxn][maxn],d[maxn][maxn];
int n,m,k,sx,sy,tx,ty,ans;
int dx[5]={-1,1,0,0},dy[5]={0,0,-1,1};
set<int> r[maxn],c[maxn];

void bfs(){
    d[sx][sy]=0;
    //vis[sx][sy]=1;
    r[sx].erase(sy);
    r[sy].erase(sx);

    queue<pair<int,int>> q;
    q.push({sx,sy});

    while(q.size()){
        pair<int,int> t=q.front();
        q.pop();
        int x=t.first,y=t.second;
        if(x==tx && y==ty){
            ans=d[x][y];
            return;
        }
        //上
        int cur=x;
        while(1){
            set<int>::iterator it=c[y].lower_bound(cur);
            if(it==c[y].begin()){break;}
            --it;
            if(x-*it>k || mp[*it][y]==0) {break;}
            cur=*it;
            d[cur][y]=d[x][y]+1;
            c[y].erase(cur);
            r[cur].erase(y);
            q.push({cur,y});
        }
        //下
        cur=x;
        while(1){
            set<int>::iterator it=c[y].upper_bound(cur);
            if(it==c[y].end()){break;}
            if(*it-x>k || mp[*it][y]==0) {break;}
            cur=*it;
            d[cur][y]=d[x][y]+1;
            c[y].erase(cur);
            r[cur].erase(y);
            q.push({cur,y});
        }
        //左
        cur=y;
        while(1){
            set<int>::iterator it=r[x].lower_bound(cur);
            if(it==r[x].begin()){break;}
            --it;
            if(y-*it>k || mp[x][*it]==0) {break;}
            cur=*it;
            d[x][cur]=d[x][y]+1;
            c[cur].erase(x);
            r[x].erase(cur);
            q.push({x,cur});
        }
        //右
        cur=y;
        while(1){
            set<int>::iterator it=r[x].upper_bound(cur);
            if(it==r[x].end()){break;}
            if(*it-y>k || mp[x][*it]==0) {break;}
            cur=*it;
            d[x][cur]=d[x][y]+1;
            c[cur].erase(x);
            r[x].erase(cur);
            q.push({x,cur});
        }
    }
}

int main()
{
    cin>>n>>m>>k;
    //读入与初始化
    for(int i=1;i<=n;i++){
        string s;cin>>s;
        for(int j=1;j<=m;j++){
            if(s[j-1]=='.') mp[i][j]=1;        //1是空位置 0是有垃圾
            r[i].insert(j);
            c[j].insert(i);
        }
    }
    cin>>sx>>sy>>tx>>ty;
    ans=-1;
    bfs();
    cout<<ans;
    return 0;
}