關於圖中邊權非零即一的寬度優先搜索c++
譯自 BalticOI 2011 Day1 T3「Switch the Lamp On」
有一種正方形的電路元件,在它的兩組相對頂點中,有一組會用導線鏈接起來,另外一組則不會。
有 N×MN\times MN×M 個這樣的元件,你想將其排列成 NNN 行 MMM 列放在電路板上。電路板的左上角鏈接電源,右下角鏈接燈泡。
試求:至少要旋轉多少個正方形元件才能讓電源與燈泡連通,若無解則輸出 NO SOLUTION。spa
記得以前誰的講課裏提到過這種「ex-BFS」?3d
只須要在隊列拓展的時候稍做更改:邊權爲一時在隊尾插入;邊權爲零在隊頭插入。正確性能夠由反證法獲得。code
1 #include<bits/stdc++.h> 2 3 struct point 4 { 5 int x,y; 6 point(int a=0, int b=0):x(a), y(b) {} 7 }; 8 int n,m,dis[533][533]; 9 char str[533][533]; 10 std::deque<point> q; 11 12 bool legal(int x, int y) 13 { 14 return x>=0&&y>=0&&x<=n&&y<=m; 15 } 16 bool check(int x, int y) 17 { 18 return str[x][y]=='\\'; 19 } 20 void update(int x, int y, int v) 21 { 22 if (dis[x][y] > v){ 23 dis[x][y] = v; 24 if (q.empty()||v > dis[q.front().x][q.front().y]) 25 q.push_back(point(x, y)); 26 else q.push_front(point(x, y)); 27 } 28 } 29 int main() 30 { 31 memset(dis, 0x3f3f3f3f, sizeof dis); 32 scanf("%d%d",&n,&m); 33 if ((n+m)%2){ 34 puts("NO SOLUTION"); 35 return 0; 36 } 37 for (int i=1; i<=n; i++) scanf("%s",str[i]+1); 38 dis[0][0] = 0, q.push_front(point(0, 0)); 39 while (q.size()) 40 { 41 point tt = q.front(); 42 q.pop_front(); 43 if (legal(tt.x+1, tt.y+1)){ 44 if (check(tt.x+1, tt.y+1)) 45 update(tt.x+1, tt.y+1, dis[tt.x][tt.y]); 46 else update(tt.x+1, tt.y+1, dis[tt.x][tt.y]+1); 47 } 48 if (legal(tt.x+1, tt.y-1)){ 49 if (check(tt.x+1, tt.y)) 50 update(tt.x+1, tt.y-1, dis[tt.x][tt.y]+1); 51 else update(tt.x+1, tt.y-1, dis[tt.x][tt.y]); 52 } 53 if (legal(tt.x-1, tt.y+1)){ 54 if (check(tt.x, tt.y+1)) 55 update(tt.x-1, tt.y+1, dis[tt.x][tt.y]+1); 56 else update(tt.x-1, tt.y+1, dis[tt.x][tt.y]); 57 } 58 if (legal(tt.x-1, tt.y-1)){ 59 if (check(tt.x, tt.y)) 60 update(tt.x-1, tt.y-1, dis[tt.x][tt.y]); 61 else update(tt.x-1, tt.y-1, dis[tt.x][tt.y]+1); 62 } 63 } 64 printf("%d\n",dis[n][m]); 65 return 0; 66 }
ENDblog