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;
}

 

posted @ 2019-11-07 20:25  毛炯人  阅读(180)  评论(0编辑  收藏  举报