洛谷P2243 电路维修
Posted Soda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷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
说明
样例的输入对应于题目描述中的情况。
只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。
/* 提交超多通过率超低的题,总而言之算法秒掉了,然而在图论上本人自带不初始化buff。 算法:我们把可以不旋转通过的边标记为0,需要旋转的标记为1,跑一次单源最短路,从左上到右下,易发现最短距离就是需要旋转的次数。 (我们可以看成每次要用到旋转后的边,需要耗费1的价值,最后价值总和当然就是答案。) 我们这样想,这是个图。可以数出来,节点数应当是(R+1)*(C+1) 建图的时候,按如下方式分配点的编号。 1 2 3 4 5 6 7 8 9 10 11 12 ...当然这是样例。我们可以发现,对于每个方格,需要标记四个点,四个点坐标可以轻易求得。 这就是这部分的作用: int pos1=((i-1)*(C+1)+j); //左上 int pos2=(i*(C+1)+j+1); //右下 int pos3=((i-1)*(C+1)+j+1); //右上 int pos4=(i*(C+1)+j); //左下 我们确定了四个点的位置,接下来就只需要连边了。(好在这道题对于内存没限制,随便开简直爽。) 如果‘/‘就右上到左下连边,这条边权值为0(val=0)。连边要连双向(未证实,我这么连得。) 同时也要双向的连一条从左上到右下的边,权值为1,表示旋转后的边。 如果是’\‘则反之。 图建好了,对于如此稠密的图我选择heap优化的dijkstra。不清楚其他单源能否过,但多源估计过不了。 最后答案就是1到(R+1)*(C+1)的最短路 我一开始用的priority_queue<pa,vector<pa>,greater<pa> >q; T一个点,换成结构体+重载运算符A了 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define maxn 260000 int T,n,m,num,head[maxn],dis[maxn],cou; bool vis[maxn]; struct node{ int to,pre,v; }e[maxn*10]; char ch[510]; void Insert(int from,int to,int v){ e[++num].to=to; e[num].v=v; e[num].pre=head[from]; head[from]=num; } int qread(){ int i=0; char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘){i=i*10+ch-‘0‘;ch=getchar();} return i; } struct Node{ int id,v; bool operator < (const Node x)const{ return v>x.v; } }; void Dij(){ priority_queue<Node>q; memset(vis,0,sizeof(vis)); memset(dis,127/3,sizeof(dis)); dis[1]=0; Node cur;cur.id=1,cur.v=0; q.push(cur); while(!q.empty()){ int point=q.top().id;q.pop(); if(vis[point])continue; vis[point]=1; if(point==cou)return; for(int i=head[point];i;i=e[i].pre){ int to=e[i].to; if(dis[to]>dis[point]+e[i].v){ dis[to]=dis[point]+e[i].v; Node nxt;nxt.id=to,nxt.v=dis[to]; q.push(nxt); } } } } int main(){ freopen("Cola.txt","r",stdin); T=qread(); while(T--){ memset(head,0,sizeof(head)); memset(e,0,sizeof(e)); num=0; n=qread();m=qread(); cou=(n+1)*(m+1); int a,b,c,d; for(int i=1;i<=n;i++){ scanf("%s",ch+1); for(int j=1;j<=m;j++){ int pos1=((i-1)*(m+1)+j);//左上 int pos2=(i*(m+1)+j+1);//右下 int pos3=((i-1)*(m+1)+j+1);//右上 int pos4=(i*(m+1)+j);//左下 if(ch[j]==‘\\‘){ Insert(pos1,pos2,0);Insert(pos2,pos1,0); Insert(pos3,pos4,1);Insert(pos4,pos3,1); } else { Insert(pos1,pos2,1);Insert(pos2,pos1,1); Insert(pos3,pos4,0);Insert(pos4,pos3,0); } } } Dij(); if(dis[cou]>=107406378)printf("NO SOLUTION\n"); else printf("%d\n",dis[cou]); } }
以上是关于洛谷P2243 电路维修的主要内容,如果未能解决你的问题,请参考以下文章