题解:P10257 [COCI 2023/2024 #5] Zlagalica

· · 题解

今天考试正好考到了,来交一交题解 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

注意:

#### 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) 完结撒花!!!