题解:P10257 [COCI 2023/2024 #5] Zlagalica
2023z
·
·
题解
今天考试正好考到了,来交一交题解 qwq
题意简述
给我们 n 个拼图,每块拼图的颜色、大小和两个数字 u 表示下一块拼图的方向和 d 表示下一块拼图的起点行 / 列,以及拼图的顺序。
- 如果 $ u=0 $,将下一块拼图放在这块拼图的上边,将下一块拼图的最左边对齐这块拼图的第 $ d $ 列。
- 如果 $ u=1 $,将下一块拼图放在这块拼图的右边(当然没有拼图了就不要放了),将下一块拼图的最下边对齐这块拼图的第 $ d $ 行。
### 思路
第一眼看这题像是模拟,实际上也就是模拟,我们用一个结构体记录每一块拼图的输入信息,编号就不记录了 (因为输入时的 $ i $ 就是 $ a_i $ ),然后边输入边模拟。我们知道方向只有右和上,并且 $ u_i $ 决定 $ 1 \leq d_i \leq s_i,r_i $,所以矩阵一定是一直向上延伸的。初始将起点赋值为 $ (x,y) $ $ (1,1) $ 对于每次循环,终点 $ (x1,y1) , x1=x+a_i.r-1 , y1=y+a_i.s-1$ 计算后,从起点枚举到终点,赋值为 $ a_i.b $(颜色)。整个矩阵的高和宽也很好算,判断当前 $ x1 $ 是否大于当前边长的 $ ansx $ 坐标,更新 $ ansx $,$ y1 $ 是否大于当前 $ ansy $ 坐标,更新 $ ansy $。哦,对,还有下一次的起点,需要分情况讨论:
- 如果 $ u=0 $,$ x = x1 + 1 , y = y + a_{k_i}.d - 1
- 如果 u=1 , x = x1 - a_{k_i}.d + 1 , y = y1 + 1
注意:
#### AC code :
```cpp
#include <bits/stdc++.h>
using namespace std;
struct node
{
int r, s, u, d;
char b;
} a[30]; // 输入的各种数据
int n, k[30], ansx = 1, ansy = 1; // ansx 表示最终输出的高,ansy 表示最终输出的宽
char s[1010][1010]; // s 表示答案数组
int main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0); // 超级输入输出流 qwq
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].b >> a[i].r >> a[i].s >> a[i].u >> a[i].d;
} // 输入
int x = 1, y = 1, x1 = 0, y1 = 0; // (x, y) 表示的是起点坐标,(x1, y1) 表示的是终点坐标。初始化 (x,y) == (1, 1)
for (int i = 1; i <= n; i++)
{
cin >> k[i];
x1 = x + a[k[i]].r - 1, y1 = y + a[k[i]].s - 1; // 通过起点算出这块拼图的终点
if (x1 > ansx) // 更新 ansx
ansx = x1;
if (y1 > ansy) // 更新 ansy
ansy = y1;
for (int v = x; v <= x1; v++)
{
for (int j = y; j <= y1; j++)
{
s[v][j] = a[k[i]].b; // 把起点到终点赋值为对应的字母
}
}
if (a[k[i]].u == 0) // 判断方向,算出下一块拼图的起点
{
x = x1 + 1, y = y + a[k[i]].d - 1; // 这里是通过找规律得出的公式
}
if (a[k[i]].u == 1)
{
x = x1 - a[k[i]].d + 1, y = y1 + 1; // 这里也是
}
}
cout << ansx << ' ' << ansy << endl; // 输出
for (int i = ansx; i >= 1; i--)
{
for (int j = 1; j <= ansy; j++)
{
if (s[i][j] == '\0') // 判断这里是否被染色
s[i][j] = '.'; // 没被染色说明这里是 .
cout << s[i][j];
}
cout << endl;
}
return 0;
} // 管理员求过 qwq
```
[AC记录](https://www.luogu.com.cn/record/223218648)
完结撒花!!!