1. 程式人生 > >luogu P2243 電路維修

luogu P2243 電路維修

push hid 描述 clu 輸入輸出格式 -m 整數 ora ()

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 電路維修