[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++