题解:P13570 [CCPC 2024 重庆站] 连方

· · 题解

题意简述

给定两个字符串 a (第 1 行), b (第 7 行),仅含 #.
要求构造一个 7 \times n 的字符矩阵,满足:

  1. 1 行为 a ,第 7 行为 b

  2. 每个四连通的 # 必须是一个实心矩形,即 若某区域四连通,则其占据的行区间 [r_1,r_2] 与列区间 [c_1,c_2]内的格子都必须是 #

  3. 所有 # 在八方向下连通(即任意两个 # 可通过上/下/左/右/对角线移动互相到达)。

    极端情况

    • a , b 都全为 # ,直接输出 7# 即可。
    • a , b 其中 1 个都全为 # ,直接判无解。

简单证明: 如第 3 个样例

6
######
.####.
# 构造策略 **Step 1**:先将第 $1$ 行和第 $7$ 行内互联,可进行构造互补行。 第 $2$ 行:将 $a$ 中 `#` 变为 `.` , `.` 变为 `#`。 第 $6$ 行:将 $b$ 中 `#` 变为 `.` , `.` 变为 `#`。 构造过后,第 $1$ 行和第 $2$ 行八连通,第 $6$ 行和第 $7$ 行八连通。 **Step 2**:再将上下的八连通相连,可在 $3-5$ 行搭桥。 在第 $2$ 行找到一个位置 $x$ ,使得 $c[2][x]$ 为 `#` ,且 $c[2][x-1]$ 或者 $c[2][x+1]$ 为 `.`。 在第 $6$ 行找到一个位置 $y$ ,使得 $c[6][y]$ 为 `#` ,且 $c[6][y-1]$ 或者 $c[6][y+1]$ 为 `.`。 **Step 3**:通过构建对角线,使全图成为八连通。 示例: ```latex 27 .######.######.####.#.##### ........####..#.......##### ``` 经过第一步变为 ```latex .######.######.####.#.##### #......#......#....#.#..... ########....##.#######..... ........####..#.......##### ``` 第二步找到 $x$ 为 $2$ ,$y$ 为 $9$。 第三步变成 ```latex .######.######.####.#.##### #......#......#....#.#..... .#......................... ..######................... ........#.................. ########....##.#######..... ........####..#.......##### ``` 构造正确 # 代码示例 ```cpp #include<bits/stdc++.h> using namespace std; const int N=1e5+5; char c[10][N]; int main(){ int T,cnt1,cnt2; int n; cin>>T; while(T--){ cin>>n; for(int i=1;i<=7;i++){ for(int j=0;j<=n+1;j++)c[i][j]='.'; } cnt1=cnt2=0; for(int i=1;i<=n;i++){ cin>>c[1][i]; if(c[1][i]=='#')cnt1++; } for(int i=1;i<=n;i++){ cin>>c[7][i]; if(c[7][i]=='#')cnt2++; } if(cnt1==n&&cnt2==n){ cout<<"Yes"<<endl; for(int i=1;i<=7;i++){ for(int j=1;j<=n;j++){ cout<<'#'; } cout<<endl; } continue; } if(cnt1==n||cnt2==n){ cout<<"No"<<endl; continue; } for(int i=1;i<=n;i++){ if(c[1][i]=='.')c[2][i]='#'; else c[2][i]='.'; } for(int i=1;i<=n;i++){ if(c[7][i]=='.')c[6][i]='#'; else c[6][i]='.'; } int a,b; for(int i=1;i<=n;i++){ if(c[2][i]=='.'&&(c[2][i-1]=='#'||c[2][i+1]=='#')){ a=i; break; } } for(int i=1;i<=n;i++){ if(c[6][i]=='.'&&(c[6][i-1]=='#'||c[6][i+1]=='#')){ b=i; break; } } int l; if(b>a)l=b-a+1; else l=a-b+1; if(l==3){ c[3][a]='#'; c[4][(b+a)/2]='#'; c[5][b]='#'; } else if(l<3){ c[3][a]='#'; c[4][b]='#'; c[5][b]='#'; } else{ c[3][a]='#'; c[5][b]='#'; if(a>b)swap(a,b); for(int i=a+1;i<b;i++)c[4][i]='#'; }//太菜了,只会分类讨论 cout<<"Yes"<<endl; for(int i=1;i<=7;i++){ for(int j=1;j<=n;j++){ if(c[i][j]=='#')cout<<'#'; else cout<<'.'; } cout<<endl; } } return 0; } ```