day2.电路维修


双端队列:特殊的dijkstra


总结:回顾dijkstra的过程,就是每次找到一个距离最小的点,用其更新其他点,可以用优先队列来维护距离最小的点,发现用deque将边权为0的点插入队头,为1的点插入队
尾,效果一样,但每次操作时间复杂度由\(log(n) -> O(1)\)



电路维修

注意点的坐标和线的坐标差一格,最后应该到(n,m)

#include<cstring>
#include<iostream>
#include<algorithm>
#include<deque>

#define x first
#define y second

using namespace std;
typedef pair<int,int> PII;

const int N = 510,M = N*N;

int n,m;
char g[N][N];
int dist[N][N];
bool st[N][N];

int bfs()
{
    memset(dist,0x3f,sizeof dist);
    memset(st,0,sizeof st);
    
    dist[0][0] = 0;
    deque<PII> q;
    q.push_back({0,0});
    
    string s= "\\/\\/";
    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};// 周围四个条线
    
    while(q.size())
    {
        auto t = q.front();
        q.pop_front();
        
        if(st[t.x][t.y]) continue;
        st[t.x][t.y] = true;
        
        for(int i = 0;i < 4;i++)
        {
            int a = t.x + dx[i],b = t.y + dy[i];
            if(a < 0 || a > n || b < 0 ||b > m) continue;
            
            int ca = t.x + ix[i],cb = t.y + iy[i];
            int d = dist[t.x][t.y] + (g[ca][cb] != s[i]);
            
            if(d < dist[a][b])
            {
                dist[a][b] = d;
                
                if(g[ca][cb] != s[i]) q.push_back({a,b});
                else q.push_front({a,b});
            }
        }
    }
    return dist[n][m];
}

int main()
{
    int t;cin>>t;
    
    while(t--)
    {
        cin>>n>>m;
        for(int i = 0;i < n;i++) scanf("%s",g[i]);
        
        int t = bfs();
        
        if(t == 0x3f3f3f3f) puts("NO SOLUTION");
        else printf("%d\n",t);
    }
    return 0;
}

Tips:\表示是\\

posted @ 2022-05-12 21:56  Weitongjie  阅读(109)  评论(0)    收藏  举报