zoukankan      html  css  js  c++  java
  • 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/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Retina屏的移动设备如何实现真正1px的线
    使用Karma、Mocha实现vue单元测试
    ios中非ARC项目中引用ARC文件
    ios中Pldatabase的用法(4)
    ios中Pldatabase的用法(3)
    ios中Pldatabase的用法(2)
    ios中修改数字键盘
    asyncsocket的用法
    ios中Pldatabase的用法
    ios中打包
  • 原文地址:https://www.cnblogs.com/sunjianzhao/p/13628830.html
Copyright © 2011-2022 走看看