• AcWing175电路维修


    这是一道在luogu的蓝题,在yxc大佬的讲解下AC掉了(百般调试)

    首先这道题给了一个字符串矩阵,/ 表示相连哪两个节点,只可以走/ 所连接的两个点,但我们可以旋转每一个边,询问从1,1 走到 n+1,m+1的最小旋转次数。如果到不了就输出no。

    首先我们要明确点的坐标和对于点四周的格子上边的坐标。其次我们考虑算法,发现这个边权一个是0,一个是1,并且要搜最小步数,我们考虑狄杰斯特拉发现是可行的,所以这也证明了bfs是正确的,然后对于这种问题我们采用stl_deque来写。对于deque,我们对于每一个点进行dijksra式的扩展,假如这个点作为过front,那么打标记,但入队后不需要打标记,和普通的队列不一样,因为这里存在多次进队的可能。然后运用四个方向数组以及一个正确匹配的边进行判断权值是1还是0,松弛dist[tx][ty],假如松弛成功,我们将其入队,边权为0放到front,边权为1放到back。最后就是特判,假如终点的横纵坐标为奇数,肯定到不了。

    1.对于格子图和块图要分清楚,方向数组写好,最后答案,越界判断细心写

    2.多组数据,千万别return 0了,特判的放在输入后面,还有memset

    3.deque: 权0前1后,打当过head的点标记

    代码

    #include<bits/stdc++.h>
    #define maxn 505
    using namespace std;
    char mp[maxn][maxn];
    bool st[maxn][maxn];
    int dist[maxn][maxn];
    int n,m;
    int xx[maxn],yy[maxn];
    int T;
    /*int dx[4]={-1,1,-1,1};
    int dy[4]={-1,-1,1,1};
    int ix[4]={-1,-1,0,0};
    int iy[4]={-1,0,-1,0}; 
    char cs[]="\//\";*/
    char cs[] = "\/\/";
    int dx[4] = {-1, -1, 1, 1}, dy[4] = {-1, 1, 1, -1};
    int ix[4] = {-1, -1, 0, 0}, iy[4] = {-1, 0, 0, -1};
    struct node{
        int x,y;
    };
    int bfs(){
        memset(dist,0x3f,sizeof(dist));
        memset(st,false,sizeof(st));
        dist[1][1]=0;    
        deque<node>q;
        q.push_back({1,1});
        while(q.size()){
            node a=q.front();
            q.pop_front();        
            if(st[a.x][a.y]==true) continue;//只可以被当做一次堆顶 
            st[a.x][a.y]=true;
            for(int i=0;i<=3;i++){
                int tx=a.x+dx[i];
                int ty=a.y+dy[i];
                if(tx<1||ty<1||tx>n+1||ty>m+1) continue;
                int gx=a.x+ix[i];
                int gy=a.y+iy[i];
                int w=0;
                if(mp[gx][gy]!=cs[i]){
                    w=1;
                }
                int d=w+dist[a.x][a.y];
                if(d<dist[tx][ty]){
                    dist[tx][ty]=d;                
                    if(w==1) q.push_back({tx,ty});//权为1,后插 
                    else q.push_front({tx,ty});//权为0,前插 
                }
            }
        }    
        return dist[n+1][m+1];
    }
    int main(){
        cin>>T;
        while(T--){
            cin>>n>>m;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++){
                    cin>>mp[i][j];
                }
            }
            if((n+m)%2!=0){
                cout<<"NO SOLUTION"<<endl;
                continue;
            }        
        cout<<bfs()<<endl;            
        } 
        return 0;
    }
  • 相关阅读:
    进程之管道Pipe,数据共享Manager,进程池Poo
    进程之锁,信息量,事件,队列,生产者消费者模型,joinablequeue
    网络编程之sock server,自定义一个与sock server类相似的功能,支持多客户端通信
    网络编程之粘包解决方案
    进程之进程创建的两种方式,两种传值的方式,验证进程间数据隔离,join,守护进程,僵尸进程,孤儿进程
    毕业设计开题报告任务书参考文献格式和数量要求
    剑指offer-替换空格
    剑指offer-二维数组中的查找
    用forward和sendRedirect转发时的区别
    ServletContext实现显示用户在线人数
  • 原文地址:https://www.cnblogs.com/china-mjr/p/11815342.html
Copyright © 2020-2023  润新知