p1864

 我承认是看了这题后想起来和p1864有点重合而且那个坑还没填就去先写了p1864。

那么我可以在较短的时间内处理出每个点到最近的危险点的距离,剩下的就是找路径了。

刚开始我还是想用dfs,但是手残的我调试的并不是很成功。如果每个点只经过一次是不一定优的,因为从这个方向来的和从另一个方向来的最短距离还不一样。如果处理出所有的路径复杂度就爆炸,用了一个优化还是不行。

那么我改怎么办呢。

还记得上一篇讲p1864的时候说过答案最大也不过是1000,为什么不二分答案呢?

二分查找[0,d[topx][topy]],每次询问的时间是m*n的,只需要dfs一遍,没经过的点进去,如果距离小于询问的答案就标记不能到达,退出;否则就是在当前答案下可以到达的,标记可以到达,向旁边dfs。这样子每次询问时每个点最多进一次退一次复杂度是m*n。

二分真是太好用了嘿嘿嘿。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<set>
using namespace std;
int d[510][510],ox[200000],oy[200000],sum,now,minn;
int i,f,tx,ty,topx,topy,endx,endy;
int n,m,ans;
char t;
int flag[510][510];
void dfs(int x,int y)
{
    d[x][y]=now;
    if(x==0||x==n+1||y==0||y==m+1)
        return ;
    now++;
    if(d[x+1][y]>now)dfs(x+1,y);
    if(d[x-1][y]>now)dfs(x-1,y);
    if(d[x][y+1]>now)dfs(x,y+1);
    if(d[x][y-1]>now)dfs(x,y-1);
    now--;
}
void ddfs(int x,int y)
{
    if(minn>d[x][y])
    {
        flag[x][y]=2;
        return ;
    }
    flag[x][y]=1;
    if(flag[x+1][y]==0)ddfs(x+1,y);
    if(flag[x-1][y]==0)ddfs(x-1,y);
    if(flag[x][y+1]==0)ddfs(x,y+1);
    if(flag[x][y-1]==0)ddfs(x,y-1);
}
bool check(int now)
{
    memset(flag,0,sizeof(flag));
    for(i=1;i<=n;i++)
        flag[i][0]=flag[i][m+1]=2;
    for(i=1;i<=m;i++)
        flag[0][i]=flag[n+1][i]=2;    
    minn=now;
    ddfs(topx,topy);
    if(flag[endx][endy]==1)
        return 1;
    else return 0;
}
int main()
{
    cin>>n>>m;
    for(i=0;i<=n+1;i++)
        for(f=0;f<=m+1;f++)
            d[i][f]=100000;
        for(i=1;i<=n;i++)
        for(f=1;f<=m;f++)
        {
            cin>>t;
            if(t=='V')
                topx=i,topy=f;
            if(t=='J')
                endx=i,endy=f;
            if(t=='+')
            {
                sum++;
                ox[sum]=i;
                oy[sum]=f;
            }
        }
    tx=ox[1],ty=oy[1];
    for(i=0;i<=n+1;i++)
        for(f=0;f<=m+1;f++)
            d[i][f]=abs(i-tx)+abs(f-ty);
        for(i=2;i<=sum;i++)
        dfs(ox[i],oy[i]);
//////////////////    
    int left=0,right=d[topx][topy],mid;    
    while(left+1<right)
    {
        mid=(left+right)/2;
        if(check(mid)) left=mid;
        else           right=mid;
    }
    if(check(right))cout<<right;
    else            cout<<left;

}
原文地址:https://www.cnblogs.com/qywyt/p/9493265.html