luogu P2243 电路维修

P2243 电路维修


题目背景

Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上。在她无依无靠的时候,善良的运输队员Mark 和James 收留了她。Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙。


题目描述

有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障。飞行车的电路板设计很奇葩,如下图所示:


输入输出格式

输入格式:

输入文件包含多组测试数据。第一行包含一个整数T 表示测试数据的数目。

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

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

对于40% 的数据,R,C≤5。

对于 100% 的数据,R,C≤500,T≤5。

输出格式:

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

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


输入输出样例

输入样例#1:

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

输出样例#1:

1

说明

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

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



s酱被这题气炸了于是不写了OwO

这个题思路很神奇啊……一开始毫无思路,打开标签,“最短路”,秒懂qwq

把格子的每个交点看做一个点(用s的话说,分配一个新id)

首先看行列点的个数,一奇一偶肯定是NO SOLUTION啦(证明?黑白染色)

然后花式建边:

遇到一个‘/’,就把右上的点和左下的点连一条边权为0的边(可以直接走),同时把左上的点和右下的点连一条边权为1的边(需要改变一条边),‘\’同理

建完边后跑一遍最短路就可以啦

……跑floyd是会T没错啦,但是为什么跑spfa也会迷之TLE啊?

最后还是写了一个堆优化dijkstra才卡过的……

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int N=300000;
int t,r,c,n;
int dis[N],p[N],cnt;
bool vis[N];
char a[N];
struct node{
       int num,dis;
       bool operator < (node x) const
       {return dis>x.dis;}
}cur;
priority_queue<node>q;
struct edge{int to,nex,val;}e[N<<2];
inline void add(int u,int v,int w)
{
    e[++cnt]=(edge){v,p[u],w};
    p[u]=cnt;
}
inline void dijk()
{
    memset(dis,0x3f,sizeof(dis));dis[1]=0;
    while(!q.empty())q.pop();
    q.push((node){1,0});
    while(!q.empty())
    {
      cur=q.top();q.pop();
      if(cur.dis!=dis[cur.num])continue;
      int u=cur.num;
      for(int k=p[u];k;k=e[k].nex)
      {
        int v=e[k].to;
        if(cur.dis+e[k].val<dis[v]){
            dis[v]=cur.dis+e[k].val;
            q.push((node){v,dis[v]});
        }
      }
      if(dis[n]==0)break;
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(p,0,sizeof(p));cnt=0;
        scanf("%d%d",&r,&c);
        bool flag=0;
        if( (r&1) ^ (c&1) )flag=1;
        for(int i=1;i<=r;++i)
        {
            scanf("%s",a);cin.get();
            if(flag)continue;
            for(int j=1;j<=c;++j)
            {
                char ch=a[j-1];
                int pos1=i*(c+1)+j,pos2=(i-1)*(c+1)+j;
                if(ch==‘/‘){
                 add(pos1,pos2+1,0);add(pos2+1,pos1,0);
                  add(pos2,pos1+1,1);add(pos1+1,pos2,1);
                }
                else{
                 add(pos1,pos2+1,1);add(pos2+1,pos1,1);
                  add(pos2,pos1+1,0);add(pos1+1,pos2,0);
                }
            }
        }
        if(flag){cout<<"NO SOLUTION"<<endl;continue;}
        n=(r+1)*(c+1);
        dijk();
        cout<<dis[n]<<endl;
    }
    return 0;
}

电路维修



luogu P2243 电路维修

时间: 2024-10-13 05:01:15

luogu P2243 电路维修的相关文章

洛谷 P2243 电路维修

P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙. 题目描述 有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障.飞行车的电路板设计很奇葩,如下图所示: 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行包含一个整数T 表示测试数据的数目. 对于每组测试数据,第一行包

洛谷P2243 电路维修

P2243 电路维修 题目背景 Elf 是来自Gliese 星球的少女,由于偶然的原因漂流到了地球上.在她无依无靠的时候,善良的运输队员Mark 和James 收留了她.Elf 很感谢Mark和James,可是一直也没能给他们帮上什么忙. 题目描述 有一天 Mark 和James 的飞行车没有办法启动了,经过检查发现原来是电路板的故障.飞行车的电路板设计很奇葩,如下图所示: 输入输出格式 输入格式: 输入文件包含多组测试数据.第一行包含一个整数T 表示测试数据的数目. 对于每组测试数据,第一行包

电路维修

[题目描述]: 电路维修 [思路]: 开先看起来挺迷的,觉得没法做,搜索也写不出来... 再仔细分析题目,发现对于任意一根电路,它只有两种状态: 连着右上和坐下 连着左下和右上 要求最小的操作数. 我们可以发现,每条电线可以花费1的代价从一种状态改变为另外一种状态,那么我们可以对于已经连着的两点连一条权为0的边,没连着的连一条花费为1的边,求出从左上角到右下角的最短路即可. 注:卡\(SPFA\),建议用\(SLF\) \(or\) \(LLL\) \(or\) 堆优化的\(DJ\),此处用的\

Luogu2243电路维修

Luogu2243电路维修 传送门 原题 找到左上角到右下角的通路.可以旋转某一个方块,代价为一. lyd书上的例题2333 怎么做 将这个问题转化为从左上到右下的最短路问题.若这个角需要旋转则是权值为1的路径,否则权值为0.这个时候跑最短路就可以了. 由于路径的权值很特殊,我们可以考虑使用双端队列优化.当权值为0时从队头插入,权值为1时从队尾插入.每次取队头,这样就可以保证一直在走最优解.而不需要dijkstra堆优化或者SPFA多次寻找最优解. 码代码时还有优化注释在代码里了. 扔代码 #i

Luogu_P2243 电路维修【题解】 双端队列bfs

题面:https://www.luogu.org/problem/P2243 建边. 对角线有相连路的边权为0,没有的为1. 然后双端队列bfs求最短路. 将边权为0的到的点从队头入队. 边权为1到的点从队尾入队. 这样可以保证最优. 代码如下: #include<bits/stdc++.h> #define int long long using namespace std; const int maxn=510; int T,r,c,dis[maxn][maxn],vis[maxn][ma

【CH2601】电路维修

这是一道广搜题,难点在于对题目的理解和对细节的处理. 对于一个节点,可以向左上.左下.右上.右下四个位置扩展,根据地图的形态确定每一步扩展的代价. 将代价最小的节点放在队头,这样用双端队列来实现.每个节点最多进出队列一次,所以时间复杂度为O(r*c) 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace s

算法提高课——搜索

BFS 求最小 基迭代,不会爆栈 Flood fill算法: 可以在线性时间复杂度内,找到某个点所在的连通块. //Home键到行首,End键到行尾 AcWing 1097. 池塘计数 AcWing 1098. 城堡问题 AcWing 1106. 山峰和山谷 最短路模型: 所有边权相等时,可以在线性时间内得到单源或多源最短路(可视为特殊的dijkstra) AcWing 1076. 迷宫问题 AcWing 188. 武士风度的牛 AcWing 1100. 抓住那头牛 AcWing 173. 矩阵

学习 研究 修理 ,维修, 电路, 家电

修理 ,维修, 电路, 家电 http://www.haohetao.com/thread-1024305-1-1.html wwbl ft0http://www.haohetao.com/thread-1024306-1-1.html wwbl ft1http://www.haohetao.com/thread-1024308-1-1.html wwbl ft2http://www.haohetao.com/thread-1024309-1-1.html wwbl ft3http://www.

维修电路

两个点,如果有线连接,则边权为0,否则边权为1 如果扩展到一个点,边权是0,则把这个点加入到队列的首端,因为对于权值来说,相当于没扩展 这就是双端队列,这里如果将将要加入的距离与队头的距离比较,会错??? 注意不能map[xx][yy]=='\',要map[xx][yy]=='\\' 这个代码是照蓝书抄的,这是一个很巧妙的办法,每个map中的x和y都是要比较的两个x和y中的较小值 而我之前写的把点编号的方法一定会MLE,更不必说直接上四维数组的了 还容易写错 1 #include<iostrea