专栏文章

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

P10257题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@mioy03w6
此快照首次捕获于
2025/12/03 02:59
3 个月前
此快照最后确认于
2025/12/03 02:59
3 个月前
查看原文
今天考试正好考到了,来交一交题解 qwq

题意简述

给我们 nn 个拼图,每块拼图的颜色、大小和两个数字 uu 表示下一块拼图的方向和 dd 表示下一块拼图的起点行 / 列,以及拼图的顺序。
uudd 的具体操作如下:
  • 如果 u=0u=0,将下一块拼图放在这块拼图的上边,将下一块拼图的最左边对齐这块拼图的第 dd 列。
  • 如果 u=1u=1,将下一块拼图放在这块拼图的右边(当然没有拼图了就不要放了),将下一块拼图的最下边对齐这块拼图的第 dd 行。

思路

第一眼看这题像是模拟,实际上也就是模拟,我们用一个结构体记录每一块拼图的输入信息,编号就不记录了 (因为输入时的 ii 就是 aia_i ),然后边输入边模拟。我们知道方向只有右和上,并且 uiu_i 决定 1disi,ri1 \leq d_i \leq s_i,r_i,所以矩阵一定是一直向上延伸的。初始将起点赋值为 (x,y)(x,y) (1,1)(1,1) 对于每次循环,终点 (x1,y1),x1=x+ai.r1,y1=y+ai.s1 (x1,y1) , x1=x+a_i.r-1 , y1=y+a_i.s-1 计算后,从起点枚举到终点,赋值为 ai.ba_i.b(颜色)。整个矩阵的高和宽也很好算,判断当前 x1x1 是否大于当前边长的 ansxansx 坐标,更新 ansxansxy1y1 是否大于当前 ansyansy 坐标,更新 ansyansy。哦,对,还有下一次的起点,需要分情况讨论:
  • 如果 u=0u=0x=x1+1,y=y+aki.d1x = x1 + 1 , y = y + a_{k_i}.d - 1
  • 如果 u=1u=1x=x1aki.d+1,y=y1+1x = x1 - a_{k_i}.d + 1 , y = y1 + 1
注意:
xx 坐标要从 ansxansx11 输出,yy 坐标可以从 11ansyansy 输出,最后判断如果这个点位为空输出 . 否则输出对应的字母。

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

评论

2 条评论,欢迎与作者交流。

正在加载评论...