【搜索 ex-BFS】bzoj2346: [Baltic 2011]Lamp
关于图中边权非零即一的宽度优先搜索
Description
译自 BalticOI 2011 Day1 T3「Switch the Lamp On」
有一种正方形的电路元件,在它的两组相对顶点中,有一组会用导线连接起来,另一组则不会。
有 N×MN\times MN×M 个这样的元件,你想将其排列成 NNN 行 MMM 列放在电路板上。电路板的左上角连接电源,右下角连接灯泡。
试求:至少要旋转多少个正方形元件才能让电源与灯泡连通,若无解则输出 NO SOLUTION。
题目分析
记得之前谁的讲课里提到过这种“ex-BFS”?
只需要在队列拓展的时候稍作更改:边权为一时在队尾插入;边权为零在队头插入。正确性可以由反证法得到。
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 }
END