zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营4 G-街机争霸 广搜

    G-街机争霸

    https://ac.nowcoder.com/acm/contest/4680/G

    题解

    ​ 一道还算正常的广搜题,对于不断移动僵尸,看看数据范围就明白了,移动范围不超过10, 那我们就可以增加一维时间来记录状态mp[x,y,t]表示在(x,y)坐标,t时刻的状态,因为僵尸只移动k步,所以(2*k-2) 步之后地图又完全一样了,所以(t<20)。把状态确定好之后就直接搜索板子一套就好了。

    感想

    ​ 好久没打过广搜了,一开始竟然觉得深搜也行,心想状态就那么几种。结果连样例都过不了,于是恍然大悟,深搜可不能保证每个状态加入队列一次,因为可能有更短的时间在之后才搜到,然后改成了广搜。样例过了,但是它一直说超过内存限制,这就很迷了。看了半天不知道拿错了,吃完午饭回来,想反正找不出错,不如看看我是不是入队的元素太多了。理论上不会超过(5*10^6), 我就加了在代码中加了一条,(if (Q.size()>5000000) return 0) , 结果答案错误,那肯定是入队的元素太多了,但是我每个状态都标记了,这就很奇怪了。又想了一会,才发现我是在出队列才标记,如队列没有标记。那肯定会出现重复入队,然后终于AC了,真是悲催。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 510
    #define ll long long
    const int INF=1e9+7;
    int n,m,mo,ans=INF,sx,sy;
    char mp1[N][N];
    bool mp2[N][N][20];
    bool f[N][N][20];
    int lx[4]={0,0,-1,1};
    int ly[4]={-1,1,0,0};
    bool flag=false;
    void readChar(char& c){
        c=getchar();
        while(c!='A' && c!='L' && c!='&' && c!='#') c=getchar();
    }
    struct Point{int x, y, sum;};
    bool dfs(){
        int tot=0;
        if (mp2[sx][sy][0]==1) return 0;
        queue<Point>Q;
        Q.push(Point{sx,sy,0});
        int x,y,t,sum;
        Point u;
        while(!Q.empty()){
            //cout<<Q.size()<<endl;
            u=Q.front(); Q.pop();
            x=u.x; y=u.y; t=u.sum%mo; sum=u.sum;
            f[x][y][t]=1;
            if (mp1[x][y]=='A'){flag=1; ans=min(ans,sum);return 1;}
            t=(t+1)%mo;
            sum++;
            for(int i=0;i<4;i++){
                tot++;
                int xx=lx[i]+x, yy=ly[i]+y;
                if (xx<1 || xx>n || yy<1 || yy>m)continue;
                if (mp2[xx][yy][t]) continue;
                if (mp1[xx][yy]=='&')continue;
                if (f[xx][yy][t])continue;
                f[xx][yy][t]=1;
                Q.push(Point{xx,yy,sum});
            }
        }
        return 0;
    }
    void work(){
        int num,k;
        cin>>n>>m>>num>>k;
        mo=2*k-2;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                readChar(mp1[i][j]);
                if (mp1[i][j]=='L'){sx=i;sy=j;}
            }
        for(int i=1;i<=num;i++){
            int x,y; string c;
            cin>>x>>y>>c;
            if (c[0]=='U'){
                int t=0;
                for(int j=x;t<=k-1;j--,t++)mp2[j][y][t]=1;
                for(int j=x-k+2;t<2*k-2;j++,t++)mp2[j][y][t]=1;
            }
            if (c[0]=='D'){
                int t=0;
                for(int j=x;t<=k-1;j++,t++)mp2[j][y][t]=1;
                for(int j=x+k-2;t<2*k-2;j--,t++)mp2[j][y][t]=1;
            }
            if (c[0]=='L'){
                int t=0;
                for(int j=y;t<=k-1;j--,t++)mp2[x][j][t]=1;
                for(int j=y-k+2;t<2*k-2;j++,t++)mp2[x][j][t]=1;
            }
            if (c[0]=='R'){
                int t=0;
                for(int j=y;t<=k-1;j++,t++)mp2[x][j][t]=1;
                for(int j=y+k-2;t<2*k-2;j--,t++)mp2[x][j][t]=1;
            }
        }
        bool flag=dfs();
        if (flag)cout<<ans;
        else cout<<"Oh no";
    }
    int main(){
        //ios::sync_with_stdio(false);
        //cin.tie(0);
        work();
        
    }
    
    
    
  • 相关阅读:
    山东财经大学新生赛暨天梯赛选拔赛 A 骆驼拼写法
    Code 墓地 问题 A: 看电视(区间贪心)
    第九届蓝桥杯 乘积尾零(Java大数)
    《真正的力量来自内心深处》
    蓝桥杯训练 历届试题 买不到的数目 (猜公式)
    前缀和与差分 算法详解
    蓝桥杯训练 历届试题 回文数字 (暴力求解,毫无任何技术含量)
    蓝桥杯训练 历届试题 最大子阵 (只用了前缀和,没用dp写)
    实习开始
    MVC缺点总结
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/12373746.html
Copyright © 2011-2022 走看看