P6265
题目大意
将
n
n
n 个矩形叠放,求它们的周长,并输出它们的轮廓。
注意:左右两边必须以轮廓开始且输出的是轮廓的周长(并不是 # 的总和)。
思路
直接的修改是最简单的,如果你每一次都算出当次的现状,是很复杂的,我们考虑先修改,后面再决定哪些是有用的。
设
b
i
,
j
b_{i,j}
bi,j 为第
i
i
i 行第
j
j
j 列的元素,且
0
0
0 为空,
1
1
1 为轮廓。
所以写出如下代码:
for(int i=1;i<=n;i++){
cin>>l>>r>>h;
r--;
H=max(H,h);
L=min(L,l);
R=max(R,r);
for(int i=1;i<=h;i++)b[i][l]=b[i][r]=1;
for(int j=l;j<=r;j++)b[h][j]=1;
}
注意,此时维护
H
H
H 与
L
L
L 与
R
R
R 的值,是为了方便后面的修改与输出,至于为什么
r
r
r 要减少可以看样例(数一下修改的范围可知,每次只修改
[
l
,
r
−
1
]
[l,r-1]
[l,r−1] 区间内的)。
接下来到了最难的地方,我们如何知道那些轮廓是无用的呢?
发现个必然的事情:对于所有不需要的轮廓,一定在一些需要的轮廓的包围中。
所以有以下方法:对于每一列,从高到低依次扫描,扫到 # 退出把以自己为中心的八个方向一共九个打上标记,用
x
x
x 数组维护。因为这种方法就像雨落下来一样,且我也没听说过这种方法,所以我叫它暴雨法。此时,就有所有不需要的轮廓,设它在的位置为
i
,
j
i,j
i,j 则
x
i
,
j
≠
1
x_{i,j}\ne 1
xi,j=1 很好理解,你都在其他轮廓的包含里,自然不可能会被赋值。
接下来我们思考另一个问题:如何统计周长?
还是采用暴雨法,对于
i
,
j
i,j
i,j 统计
b
i
−
1
,
j
+
b
i
+
1
,
j
+
b
i
,
j
−
1
+
b
i
,
j
+
1
b_{i-1,j}+b_{i+1,j}+b_{i,j-1}+b_{i,j+1}
bi−1,j+bi+1,j+bi,j−1+bi,j+1 的值,退出方法与上述无异,所以可以合一起写。
代码:
for(int i=L-1;i<=R+1;i++)for(int j=H+1;j>=1;j--){
if(b[j][i])break;
x[j-1][i-1]=x[j-1][i]=x[j-1][i+1]=x[j][i-1]=x[j][i]=x[j][i+1]=x[j+1][i-1]=x[j+1][i]=x[j+1][i+1]=1;
sum+=b[j-1][i]+b[j+1][i]+b[j][i-1]+b[j][i+1];
}
接下来就是输出,只有满足本身为 # 且被复制的才会输出 # 否则不会。
代码:
cout<<sum<<"\n";
for(int i=H;i>=1;i--){
for(int j=L;j<=R;j++)cout<<(b[i][j]&&x[i][j]?'#':'.');
cout<<"\n";
}
for(int i=L;i<=R;i++)cout<<'*';
注意事项
- 注意雨流的方向(不能从左向右流,只能从上到下)。
- 注意起始位置(不能让边界没扫出来)。
- 注意雨流的顺序,是从上往下的(
你回到过去不就从下往上了吗)。
代码
#include<bits/stdc++.h>
using namespace std;
int n,L=1005,R,l,r,h,H,z[1005],sum;
bool b[1005][1005],x[1005][1005];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>l>>r>>h;
r--;
H=max(H,h);
L=min(L,l);
R=max(R,r);
for(int i=1;i<=h;i++)b[i][l]=b[i][r]=1;
for(int j=l;j<=r;j++)b[h][j]=1;
}
for(int i=L-1;i<=R+1;i++)for(int j=H+1;j>=1;j--){
if(b[j][i])break;
x[j-1][i-1]=x[j-1][i]=x[j-1][i+1]=x[j][i-1]=x[j][i]=x[j][i+1]=x[j+1][i-1]=x[j+1][i]=x[j+1][i+1]=1;
sum+=b[j-1][i]+b[j+1][i]+b[j][i-1]+b[j][i+1];
}
cout<<sum<<"\n";
for(int i=H;i>=1;i--){
for(int j=L;j<=R;j++)cout<<(b[i][j]&&x[i][j]?'#':'.');
cout<<"\n";
}
for(int i=L;i<=R;i++)cout<<'*';
return 0;
}
//BluePoch-1999