這是一道在luogu的藍題,在yxc大佬的講解下AC掉了(百般調試)node
首先這道題給了一個字符串矩陣,/ \表示相連哪兩個節點,只能夠走/ \所鏈接的兩個點,但咱們能夠旋轉每個邊,詢問從1,1 走到 n+1,m+1的最小旋轉次數。若是到不了就輸出no。c++
首先咱們要明確點的座標和對於點四周的格子上邊的座標。其次咱們考慮算法,發現這個邊權一個是0,一個是1,而且要搜最小步數,咱們考慮狄傑斯特拉發現是可行的,因此這也證實了bfs是正確的,而後對於這種問題咱們採用stl_deque來寫。對於deque,咱們對於每個點進行dijksra式的擴展,假如這個點做爲過front,那麼打標記,但入隊後不須要打標記,和普通的隊列不同,由於這裏存在屢次進隊的可能。而後運用四個方向數組以及一個正確匹配的邊進行判斷權值是1仍是0,鬆弛dist[tx][ty],假如鬆弛成功,咱們將其入隊,邊權爲0放到front,邊權爲1放到back。最後就是特判,假如終點的橫縱座標爲奇數,確定到不了。算法
1.對於格子圖和塊圖要分清楚,方向數組寫好,最後答案,越界判斷細心寫數組
2.多組數據,千萬別return 0了,特判的放在輸入後面,還有memsetspa
3.deque: 權0前1後,打當過head的點標記調試
代碼code
#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; }