AcWing 175. 電路維修(雙端隊列BFS)

題幹:

達達是來自異世界的魔女,她在漫無目的地四處漂流的時候,遇到了善良的少女翰翰,從而被收留在地球上。
翰翰的家裏有一輛飛行車。
有一天飛行車的電路板突然出現了故障,導致無法啓動。
電路板的整體結構是一個R行C列的網格(R,C≤500),如下圖所示。
在這裏插入圖片描述
每個格點都是電線的接點,每個格子都包含一個電子元件。
電子元件的主要部分是一個可旋轉的、連接一條對角線上的兩個接點的短電纜。
在旋轉之後,它就可以連接另一條對角線的兩個接點。
電路板左上角的接點接入直流電源,右下角的接點接入飛行車的發動裝置。
達達發現因爲某些元件的方向不小心發生了改變,電路板可能處於斷路的狀態。
她準備通過計算,旋轉最少數量的元件,使電源與發動裝置通過若干條短纜相連。
不過,電路的規模實在是太大了,達達並不擅長編程,希望你能夠幫她解決這個問題。
注意:只能走斜向的線段,水平和豎直線段不能走。
輸入格式
輸入文件包含多組測試數據。
第一行包含一個整數T,表示測試數據的數目。
對於每組測試數據,第一行包含正整數R和C,表示電路板的行數和列數。
之後R行,每行C個字符,字符是"/“和”"中的一個,表示標準件的方向。
輸出格

對於每組測試數據,在單獨的一行輸出一個正整數,表示所需的縮小旋轉次數。
如果無論怎樣都不能使得電源和發動機之間連通,輸出NO SOLUTION。

數據範圍
1≤R,C≤500
1≤T≤5
輸入樣例:
1
3 5
\/\
\///
/\\
輸出樣例:
1
樣例解釋
樣例的輸入對應於題目描述中的情況。
只需要按照下面的方式旋轉標準件,就可以使得電源和發動機之間連通。
在這裏插入圖片描述

思路:

如果直接暴力模擬的話比較難寫,然後考慮到要我們求的是最少變化次數,然後電纜可以認爲是從左上角的點到右下角的點,類似於求最短路。
這樣我們開始思考怎麼建圖,‘/’認爲是從右上角到左下角,‘\’是從左上角到右下角。例:(0,0)對’ \ '如果走到(1,1)權值是0,如果走到(1,-1)則權值是1.(即從起點枚舉所有方向,然判斷當前走向是否需要變化電纜方向)。既然最短路權值只有0和1,那我們可以用雙端隊列BFS,我們要求的是最少消耗,那肯定是儘量先走權值爲0的路,後走權值爲1的路,然後我們搞一個雙端隊列,權值0入隊首,權值1入隊尾,這樣可以保證隊列單調性和兩端性(因爲0一定在前半段,1在後半段)。這樣就變成了複雜度o(m)的最短路問題。
細節見代碼:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef pair<int,int> PII;
int n,m,dis[510][510];
int d[4][2]={{-1,-1},{-1,1},{1,1},{1,-1}};//點的四個移動方向
int dt[4][2]={{-1,-1},{-1,0},{0,0},{0,-1}};//四個方向的圖的位移
char ch[510][510];
bool vis[510][510];
char tu[]={"\\/\\/"};
int bfs(){
    deque<PII> q;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[0][0]=0;
    q.push_front({0,0});
    //vis[0]=true;
    //BFS
    while(q.size()){
        PII t=q.front();
        q.pop_front();
        int x=t.first,y=t.second;
        if(x==n&&y==m)
            return dis[x][y];
        if(vis[x][y])
            continue;
        vis[x][y]=true;
        for(int i=0;i<4;i++){
            int tx=x+d[i][0],ty=y+d[i][1];
            if(tx<0||ty<0||tx>n||ty>m)
                continue;
            int cx=x+dt[i][0],cy=y+dt[i][1];
            int distance=dis[x][y]+(ch[cx][cy]!=tu[i]);
            if(distance<dis[tx][ty]){
                dis[tx][ty]=distance;
                if(ch[cx][cy]!=tu[i])
                    q.push_back({tx,ty});
                else
                    q.push_front({tx,ty});
            }
        }
    }
    return 0x3f3f3f3f;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%s",ch[i]);
        int ans=bfs();
        //找不到路
        if(n+m&1||ans==0x3f3f3f3f)
            printf("NO SOLUTION\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章