电路维修-------------------------双端队列广搜

达达是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女翰翰,从而被收留在地球上。

翰翰的家里有一辆飞行车。

有一天飞行车的电路板突然出现了故障,导致无法启动。

电路板的整体结构是一个R行C列的网格(R,C≤500),如下图所示。

电路.png

每个格点都是电线的接点,每个格子都包含一个电子元件。

电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。

在旋转之后,它就可以连接另一条对角线的两个接点。

电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。

达达发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。

她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。

不过,电路的规模实在是太大了,达达并不擅长编程,希望你能够帮她解决这个问题。

注意:只能走斜向的线段,水平和竖直线段不能走。

输入格式
输入文件包含多组测试数据。

第一行包含一个整数T,表示测试数据的数目。

对于每组测试数据,第一行包含正整数R和C,表示电路板的行数和列数。

之后R行,每行C个字符,字符是"/“和”"中的一个,表示标准件的方向。

输出格式
对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。

如果无论怎样都不能使得电源和发动机之间连通,输出NO SOLUTION。

数据范围
1≤R,C≤500,
1≤T≤5
输入样例:
1
3 5
\/\
\///
/\\
输出样例:
1
样例解释
样例的输入对应于题目描述中的情况。

只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。
在这里插入图片描述

解析:
本题存在两个权重,一个是1(需要旋转电线),一个是0(连通好的)。把权重为0的放到队头,权重为1的放到队尾然后bfs
还有一个性质:
如果横纵坐标之和是奇数的话,那么一定不能走到


#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int>PII;
int t,n,m;
int dist[1005][1005];
bool st[1005][1005];
char s[1005][1005];
  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}; //某个点四周边的方向
int bfs()
{
    memset(dist,0x3f,sizeof dist);
    memset(st,0,sizeof st);
    deque<PII>q;
    q.push_back({0,0});
    dist[0][0]=0;//初始化
  //  st[0][0]=true;
    char cs[] = "\\/\\/";
    while(q.size())
    {
        auto t=q.front();
        q.pop_front();
        if(st[t.x][t.y]) continue;
        st[t.x][t.y]=true;
        for(int i=0;i<4;i++)
        {
            int xx=t.x+dx[i];
            int yy=t.y+dy[i];
            if(xx<0||xx>n||yy<0||yy>m) continue;//判断边界
            int ca=t.x+ix[i];int cb=t.y+iy[i];//找边的位置
            int d=dist[t.x][t.y]+(s[ca][cb]!=cs[i]);//更新距离,如果当前的边和找的边需要旋转才能连通,权值+1
            if(d<dist[xx][yy]) //更新最小
            {
                dist[xx][yy]=d;
                if(s[ca][cb]!=cs[i]) q.push_back({xx,yy}); //把权重为1的放到队尾
                else q.push_front({xx,yy});//把权重为0的放到队首
            }
        }
    }
    return dist[n][m];
}
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++) cin>>s[i];
        if((n+m)&1) puts("NO SOLUTION"); //如果横纵坐标之和是奇数那么一定无法到达
        else
        {
            printf("%d\n",bfs());
        }
    }
}
发布了383 篇原创文章 · 获赞 7 · 访问量 8041

猜你喜欢

转载自blog.csdn.net/qq_43690454/article/details/104236263
今日推荐