[CSP-S模拟测试]:引子(大模拟)

题目描述

网上冲浪时,$Slavko$被冲到了水箱里,水箱由上而下竖直平面。示意图如下:


数字$i$所在的矩形代表一个编号为$i$的水箱。
1号水箱为水箱中枢,有水管连出。除了$1$号水箱外,其他水箱上方会接进来恰好一条水管,也可能有水管连出。
连出的水管会从水箱侧面连出去,同一个水箱连出去的水管会在不同的行与侧面连接。每一条水管直接连接两个水箱,这意味着不会把水管分叉也不会出现水管交叉的情况。这样,从一个水箱流入另外一个水箱时,水管的走向始终保持行号增加或保持不变。
水会源源不断地涌进$1$号水箱直到各个水箱水满为止。帮助$Slavko$计算出各个水箱装满的次序。


输入格式

输入会给你一个$n*m$的点阵,点阵字符的全集为${+,|,-,.}$
水箱:形状是矩形,四角有$+$符号,左右为$|$,上下为$-$,里面包含一个数字代表水箱的编号,如上图。
管道:一条管道恰好连接两个不同的水箱,$|$表示管道竖直摆放,$-$表示管道水平摆放,其中竖直的管道之间会连接起来,水平的管道会连接起来,$+$连接竖直和水平的管道($+$的上下恰好其中一个为$.$一个为$|$,$+$的左右恰好其中一个为$.$一个为$-$)。
其余位置用. 来填充。
输入的第$1$行为两个正整数$n$,$m$。
接下来$n$行描述点阵的信息,每行有$m$个字符。


输出格式

输出水箱被浸满的顺序,每行一个序号。


样例

样例输入1:

12 13
..+--+.......
+-|..|.......
|.|.1|--+....
|.+--+..|....
|......+----+
+---+..|..2.|
....|..+----+
.+--+........
.|...........
+---+........
|.3.|........
+---+........

样例输出1:

2
3
1

样例输入2:

8 10
..........
.......+-+
...+---|1|
...|...+-+
...|......
..+-+.....
..|2|.....
..+-+.....

样例输出2:

2
1


数据范围与提示

样例解释:

把输入粘贴到记事本上就一目了然了。

大概是这样:

样例1:     

样例2:

数据范围:

$70%$的数据:$1\leqslant n,m\leqslant 100$。
$100%$的数据满足:$1\leqslant n,m\leqslant 1,000$。


题解

就是个大模拟,但是细节颇多,注意以下几点:

 $\alpha.$可能会出现这种情况:

  

  但是不会出现这种情况:

  

 $\beta.$一个水箱可能有多个儿子,但是不会有两个儿子等高。

 $\gamma.$注意边界问题。

时间复杂度:$\Theta(hsw)$。

期望得分:$100$分。

实际得分:我也不知道……


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int x,y,lx,ly,rx,ry,s,s1,lr[100],c[100],son[100];}e[50000];
int n,m;
int Map[5000][5000];
char ch[5000];
int ex,ey,cnt;
int ans[100000];
int que[100000];
void getson(int x,int y,int id,int d,bool son)
{
	if(Map[x][y]==2&&d==2)
	{
		for(int i=1;i<=cnt;i++)
			if(e[i].lx==x&&e[i].ly<y&&e[i].ry>y)
			{
				e[id].son[++e[id].s1]=i;
				break;
			}
		return;
	}
	if(Map[x][y]==1)
	{
		if(Map[x+1][y]==3)getson(x+1,y,id,2,son);
		if(Map[x][y-1]==2&&d!=1)getson(x,y-1,id,0,son);
		if(Map[x][y+1]==2&&d!=0)getson(x,y+1,id,1,son);
	}
	else if(d==2)getson(x+1,y,id,2,son);
	else if(d==0)getson(x,y-1,id,d,son);
	else if(d==1)getson(x,y+1,id,d,son);
}
void dfs(int x)
{
	if(!e[x].s){ans[++ans[0]]=x;return;}
	if(e[x].s)
		for(int i=1;i<=e[x].s;i++)
			dfs(e[x].son[i]);
	ans[++ans[0]]=x;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",ch+1);
		for(int j=1;j<=m;j++)
		{
			switch(ch[j])
			{
				case '+':Map[i][j]=1;break;
				case '-':Map[i][j]=2;break;
				case '|':Map[i][j]=3;break;
			}
			int sz=0;
			while(ch[j]>='0'&&ch[j]<='9')
			{
				sz=sz*10+ch[j]-'0';
				j++;
			}
			if(sz)
			{
				j--;
				e[++cnt].x=i;
				e[cnt].y=j;
				que[cnt]=sz;
			}
			if(sz==1){ex=i,ey=j;}
		}
	}
	int flag;
	for(int i=1;i<=cnt;i++)
	{
		flag=e[i].y;
		while(flag--)if(Map[e[i].x][flag]==3)break;
		e[i].ly=flag;
		flag=e[i].y;
		while(flag++)if(Map[e[i].x][flag]==3)break;
		e[i].ry=flag;
		flag=e[i].x;
		while(flag--)if(Map[flag][e[i].y]==2)break;
		e[i].lx=flag;
		flag=e[i].x;
		while(flag++)if(Map[flag][e[i].y]==2)break;
		e[i].rx=flag;
		flag=e[i].rx;
		if(e[i].ry>n&&e[i].ly==1)goto nxt;
		while(flag--)
		{
			if(Map[flag][e[i].ly-1]==2||Map[flag][e[i].ly-1]==1){e[i].c[++e[i].s]=flag;e[i].lr[e[i].s]=0;}
			if(Map[flag][e[i].ry+1]==2||Map[flag][e[i].ry+1]==1){e[i].c[++e[i].s]=flag;e[i].lr[e[i].s]=1;}
			if(flag<e[i].lx)goto nxt;
		}
		nxt:;
	}
	for(int i=1;i<=cnt;i++)
		for(int j=1;j<=e[i].s;j++)
		{
			if(e[i].lr[j]==0)getson(e[i].c[j],e[i].ly-1,i,0,0);
			else getson(e[i].c[j],e[i].ry+1,i,1,1);
		}
	dfs(1);
	for(int i=1;i<=cnt;i++)printf("%d\n",que[ans[i]]);
	return 0;
}
 

rp++

posted @ 2019-08-14 15:25  HEOI-动动  阅读(280)  评论(0编辑  收藏  举报