【广搜】电路维修

题目描述

Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。
电路板的整体结构是一个R行C列的网格(R,C≤500),如右图所示。每个格点都是电线的接点,每个格子都包含一个电子元件。电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。在旋转之后,它就可以连接另一条对角线的两个接点。电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。
Ha'nyu发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。不过,电路的规模实在是太大了,Ha'nyu并不擅长编程,希望你能够帮她解决这个问题。

输入

输入包含多组测试数据。第一行包含一个整数T 表示测试数据的数目。
对于每组测试数据,第一行包含正整数R 和C,表示电路板的行数和列数。
之后R 行,每行C 个字符,字符是"/"和"\"中的一个,表示标准件的方向。

输出

对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。
如果无论怎样都不能使得电源和发动机之间连通,输出NO SOLUTION。

样例输入

1
3 5
\\/\\
\\///
/\\\\

样例输出

1

提示

对于40% 的数据,R,C≤5。
对于100% 的数据,R,C≤500,T≤5。
样例解释
样例的输入对应于题目描述中的情况。
只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。

 

【思路】

  这个是一个边权为要么1,要么0的无向图,在这样的图上,我们可以通过双端队列广搜搜索来计算。算法的整体框架与一般的广搜类似,只是在每个结点上沿分支扩展时稍作改变。如果这条分支是边权为0的边,就把沿该分支到达的新结点从队头入队;如果这条分支是边权为1的边,就像一般的广搜搜索一样从队尾入队,这样一来,我们就仍能保证任意时刻广搜搜索队列中的结点对应的距离都具有”两段性“和”单调性“,每个结点从队头出队时,就能得到从左上角到该节点的最短距离。

  因为每个节点只需要访问一次,所以算法的时间复杂度为O(R*C)

 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N = 505;
 4 int dis[N][N];
 5 char s[N][N];
 6 int n,m;
 7 typedef struct Node {
 8     int x,y;
 9 }Node;
10 deque <Node> Q ;
11 void Push ( int x,int y,int s,int k ){
12     if( s+k < dis[x][y] ){
13         dis[x][y] = s+k ;
14         if(!k)    Q.push_front ( Node{x,y} );
15         else     Q.push_back ( Node{x,y} ) ;
16     }
17 }
18 int dir[4][2] = {
19     {-1,-1} , {-1,1},
20     {1,-1}, {1,1}
21 };
22 char Str[] = {"\\//\\"};
23 void BFS(){
24     memset(dis,0x7f,sizeof dis);
25     Q.push_front ( Node{1,1} ) ;
26     dis[1][1] = 0 ;
27     while ( !Q.empty() ){
28         Node cur = Q.front();
29         Q.pop_front();
30         int x = cur.x , y = cur.y ;
31         for(int i=0;i<4;i++){
32             int tx = x + dir[i][0] ;
33             int ty = y + dir[i][1] ;
34             int dx = x + (dir[i][0] == 1 ? 0:-1) ;
35             int dy = y + (dir[i][1] == 1 ? 0:-1) ;
36             if( 1 <= tx && tx <= n+1 && 1 <= ty && ty <= m+1 ){
37                 Push(tx,ty,dis[x][y], ( Str[i] != s[dx][dy] ));
38             }
39         }
40     }
41     printf("%d\n",dis[n+1][m+1]);
42 }
43 int main()
44 {
45     int T;
46     for(scanf("%d",&T);T;T--){
47         scanf("%d%d",&n,&m);
48         for(int i=1;i<=n;i++){
49             scanf("%s",s[i]+1 );
50         }
51         if( (n+m)&1 ){
52             printf("NO SOLUTION\n");
53         }else{
54             BFS();
55         }
56     }
57     return 0;
58 }
电路维修

 

 

posted @ 2019-07-19 17:20  Osea  阅读(225)  评论(0编辑  收藏  举报