zoukankan      html  css  js  c++  java
  • 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;
    
    }
  • 相关阅读:
    史上最全Html与CSS布局技巧
    Discuz! X的CSS加载机制
    关于input框只能输入纯数字问题
    对象的数据属性
    vue中将光标定位到Input上的问题
    端口占用问题解决方案
    el-button如何消除右边计数样式
    如何改变vscode的背景颜色
    为什么——要实例化对象?
    call()&apply()
  • 原文地址:https://www.cnblogs.com/qywyt/p/9493265.html
Copyright © 2011-2022 走看看