AcWing1175电路维修(双端队列+搜索)

题目地址https://www.acwing.com/problem/content/177/

题目描述

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

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

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

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

电路.png

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

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

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

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

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

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

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

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

输入格式

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

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

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

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

输出格式

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

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

数据范围

1R,C500
1T5

题解:假设左上角的起点是(0,0),那么只有位置i+j是偶数,才会到达,因为当前在(0,0)那么每一步移动,都是沿着斜线,那么横纵坐标都会变化1,所以变化后的和还是偶数。所以,根绝这个我们便可以首先排除一些样例肯定是不会到达的,而且这个特性在后面用最短路来抽象的时候会用到。那么接下来就是抽象整个问题了,题目的问题是求最少移动多少线可以到达目的地。那么我们便可以本来有线的边看作权值是0,没有线需要移动的是1.而且这里面因为之前说过一些点不会到达,所以可以放心的将线移动。这道题可以利用双端队列+搜索来进行。

双端队列适用于:只包含0和1的最短路问题。当前点扩展出来的边的权值为0的则将边的另一个端点插入队首,为1则插入队尾。其余剩下的就和一般的bfs一样 。

AC代码:

#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
using namespace std;
const int N=510;
typedef pair<int ,int > PII;
char gr[N][N];
int dis[N][N],r,c;

int bfs(){
    deque<PII>de;
    memset(dis,0x3f,sizeof dis);
    dis[0][0]=0;
    de.push_front(make_pair(0,0));
    int rx[4]={-1,-1,1,1},ry[4]={-1,1,1,-1};//这个是对结点进行上下左右移动的,从左上角开始顺时针的存储 
    int ix[4]={-1,-1,0,0},iy[4]={-1,0,0,-1};//这个是对当前结点按照上面方法移动之后,所需要对应的边所在的数组位置的移动方法 
    char cs[]="\/\/";
    while(!de.empty()){
        PII now=de.front();de.pop_front();
        for(int i=0;i<4;i++){
            int ra=now.first+rx[i],rb=now.second+ry[i];
            if(ra<0||ra>r||rb<0||rb>c) continue;
            int ia=now.first+ix[i],ib=now.second+iy[i];
            if(dis[ra][rb]>dis[now.first][now.second]+(gr[ia][ib]!=cs[i])){
                dis[ra][rb]=dis[now.first][now.second]+(gr[ia][ib]!=cs[i]);
                if(ra==r&&rb==c) return dis[ra][rb];
                if(gr[ia][ib]!=cs[i]) de.push_back(make_pair(ra,rb));
                else de.push_front(make_pair(ra,rb));
            }
        }
    }
}

int main(){
    int t;cin>>t;
    while(t--){
        cin>>r>>c;
        for(int i=0;i<r;i++)
            for(int j=0;j<c;j++)
                cin>>gr[i][j];
        if(r+c & 1) {
            cout<<"NO SOLUTION
";
            continue;
        }
        printf("%d
",bfs());
    }
    return 0;
}

2020/9/7  19:59


作者:孙建钊
出处:http://www.cnblogs.com/sunjianzhao/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/sunjianzhao/p/13628830.html