• 双端队列(双端bfs)解决边权只包含0和1的最短路问题


    电路维修

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

    翰翰的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。电路板的整体结构是一个 R行 C 列的网格(R,C≤500),如下图所示。

     

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

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

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

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

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

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

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

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

    输入格式

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

    输出格式

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

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

    数据范围

    1≤R,C≤500,1≤T≤5

    输入样例:

    1. 1
    2. 3 5
    3. \\/\\
    4. \\///
    5. /\\\\

    输出样例:

    1
    

    样例解释

    样例的输入对应于题目描述中的情况。

    只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。

     思路:

    这道题遇到的每个器件有两种状态,一个需要旋转,一个不需要旋转,由于我们要求旋转的次数要尽量的少,所以不旋转我们可以看成是0,旋转可以看成权重是1,这和普通的宽搜就有了区别:

    普通的宽搜边权都是1,而这个有边权是0的情况,那么宽搜的特点是什么呢?

    宽搜的两个性质:

    1、两阶段性

    即开始的一段都是x,后一段都是x+1。

    2.单调性

    由两阶段性可知,长的总是在右边,即队列从开始到结束,先遇到的最短。

    那么此题中边权有0怎么办

    其实边权为0就可以看成x+0

    那是不是就理应放在左边

    于是,我们可以用一个双端队列,权重是0,加在左边,权重是1加在右边。

    代码:

    1. #include
    2. using namespace std;
    3. typedef pair<int, int> PII;
    4. const int N = 510;
    5. int n, m;
    6. char g[N][N];
    7. int dist[N][N];
    8. bool st[N][N];
    9. int bfs() {
    10. memset(dist, 0x3f, sizeof dist);
    11. memset(st, 0, sizeof st);
    12. dist[0][0] = 0;
    13. deque q;
    14. q.push_back({ 0,0 });
    15. char cs[] = "\\/\\/";
    16. int dx[4] = { -1, -1, 1, 1 }, dy[4] = { -1,1,1,-1 };
    17. int ix[4] = { -1,-1,0,0 }, iy[4] = { -1,0,0,-1 };
    18. while (q.size()) {
    19. PII t = q.front();
    20. q.pop_front();
    21. if (st[t.first][t.second])continue;
    22. st[t.first][t.second];
    23. for (int i = 0; i < 4; i++) {
    24. int a = t.first + dx[i], b = t.second + dy[i];
    25. if (a<0 || a>n || b<0 || b>m)continue;
    26. int ca = t.first + ix[i], cb = t.second + iy[i];
    27. int d = dist[t.first][t.second] + (g[ca][cb] != cs[i]);
    28. if (d < dist[a][b]) {
    29. dist[a][b] = d;
    30. if (g[ca][cb] != cs[i])q.push_back({ a,b });
    31. else q.push_front({ a,b });
    32. }
    33. }
    34. }
    35. return dist[n][m];
    36. }
    37. int main()
    38. {
    39. int T;
    40. cin >> T;
    41. while (T--) {
    42. cin >> n >> m;
    43. for (int i = 0; i < n; i++)cin >> g[i];
    44. int t = bfs();
    45. if (t == 0x3f3f3f3f)cout << "NO SOLUTION" << endl;
    46. else cout << t << endl;
    47. }
    48. return 0;
    49. }

  • 相关阅读:
    【CVPR 2023】Diffusion Models高分辨率长视频生成 Align your Latents
    hadoop项目之求出每年二月的最高气温(Combiner优化)
    C++中的强制转换
    Spring Boot中的依赖注入和自动注入
    Linux 中 ss 命令的使用实例
    nacos简单使用
    thinkphp5 URL和路由的功能详解与实例
    AntDesignVue之a-table中key不唯一问题处理的多种方式
    数组的赋值
    【Three.js】第十二章 Materials 材质
  • 原文地址:https://blog.csdn.net/qq_59183443/article/details/127909814