Fork me on GitHub

2025.8.18校队题单分享+总结

T1

P10804 [CEOI 2024] 玩具谜题

题目描述

题目译自 CEOI 2024 Day2 T1「Toy

CEOI 2024 的命题人 Ben 从科学委员会收到了一份礼物——一个玩具。这个玩具是个谜题,可以想象成一个 \(H\)\(W\) 列的网格,上面放着一个金属物体。这个金属物体由两部分组成:一个横向的 \(1\)\(K\) 列的部分和一个纵向的 \(L\)\(1\) 列的部分,这两部分松散地连接在一起。它们都不能旋转,但可以在网格内水平或垂直滑动,只要它们始终重叠在一个方格上。

网格里还有一些障碍物。金属物体的任何部分都不能穿过障碍物,更糟糕的是,它们也不能(即使部分)移出网格。Ben 的任务是将金属物体从指定起始位置移动到(可能不同的)目标位置,使得两部分重叠在指定的目标方格上。

然而,Ben 玩这个玩具已经有一段时间了,还没有解开谜题。事实上,他开始怀疑组织者在捉弄他,给了他一个无解的谜题。因此,他向你求助,想知道这个谜题是否有解。

输入格式

输入的第一行包含四个空格分隔的整数 \(W, H, K, L\),分别表示谜题的宽度、高度、横向部分的宽度和纵向部分的高度。第二行包含四个整数 \(x_h, y_h, x_v, y_v\),表示横向部分最左上角方格的坐标和纵向部分最左上角方格的坐标。

行从上到下编号为 \(0\)\(H-1\),列从左到右编号为 \(0\)\(W-1\)\(x\) 坐标表示列号,\(y\) 坐标表示行号。

接下来的 \(H\) 行每行包含 \(W\) 个字符,表示网格。字符 . 表示空方格,字符 X 表示障碍物,字符 * 表示目标方格。

保证金属物体的初始位置合法,即两部分重叠在一个方格上,并且两部分不与障碍物重叠也不超出网格。

只有一个目标方格,即玩具中只有一个字符 *,它可能与金属物体的初始位置重叠。

输出格式

如果可以将金属物体移动到目标方格,则输出一行 YES,否则输出 NO

输入输出样例 #1

输入 #1
4 3 2 2
0 1 0 0
.X.*
....
...X
输出 #1
YES

输入输出样例 #2

输入 #2
2 3 2 3
0 1 0 0
.X
.*
.X
输出 #2
NO

说明/提示

样例解释 1

初始状态如下:

我们可以先将纵向部分向下移动一格,然后尽可能地交替移动横向和纵向部分,直到无法继续。接着,我们可以将纵向部分向上并向右移动,到达目标方格,最后将横向部分向上移动,也到达目标方格。

样例解释 2

无法移动纵向部分而不碰到障碍物,因此永远无法到达目标方格。

对于所有输入数据,满足:

  • \(2 \leq W, H \leq 1\,500\)
  • \(2 \leq K \leq W, 2 \leq L \leq H\)
  • \(0 \leq x_h \leq W - K, 0 \leq y_h \leq H - 1\)
  • \(0 \leq x_v \leq W - 1, 0 \leq y_v \leq H - L\)

详细子任务附加限制及分值如下表所示。

子任务 附加限制 分值
\(1\) \(W, H \le 50\) \(14\)
\(2\) \(W, H \le 90\) \(21\)
\(3\) \(W, H \le 300, K, L \le 10\) \(9\)
\(4\) \(W, H \le 360\) \(29\)
\(5\) 无附加限制 \(27\)

先暴力,状态是横着的和竖着的的左上角坐标,如题面所示,但是这样的时间复杂度是 \(O(H^2M^2)\)
通过枚举焦点减少状态量,交点的移动其实就可以判断出横竖的移动,交点左右动就是竖着的左右动,交点上下移动就是横着的上下动,再加上前缀后缀预处理,时间复杂度就降成了 \(O(H \times M)\) ;

给一个代码:

#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

const int N = 1510;

int n, m, K, L;
int sx, sy, tx, ty;
int Dx[4] = {-1, 0, 1, 0};
int Dy[4] = {0, 1, 0, -1};
struct Node1
{
	int l, r;
};
struct Node2
{
	Node1 X, Y;
};
char edge[N][N];
Node2 f[N][N];
bool st[N][N];

bool bfs()
{
	queue<pair<int, int>> q;
	q.push({sx, sy});
	st[sx][sy] = true;
	while(q.size()) 
	{
		pair<int, int> tmp = q.front();
		q.pop();
		int x = tmp.x, y = tmp.y;
		if(x == tx && y == ty) return true;
		for(int i = 0 ; i < 4 ; i ++ ) 
		{
			int dx = x + Dx[i], dy = y + Dy[i];
			if((dx >= 1 && dx <= n && dy >= 1 && dy <= m && edge[dx][dy] != 'X' && !st[dx][dy]) == false) continue;
			if(dy == y && (min(f[dx][dy].X.r, f[x][y].X.r) - max(f[dx][dy].X.l, f[x][y].X.l) + 1 >= K))
			{
				q.push({dx, dy});
				st[dx][dy] = true;
			}else if(dx == x && (min(f[x][y].Y.r, f[dx][dy].Y.r) - max(f[dx][dy].Y.l, f[x][y].Y.l) + 1 >= L)) 
			{
				q.push({dx, dy});
				st[dx][dy] = true;
			}
		}
	}
	return false;
}
int main()
{
    ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> m >> n >> K >> L;
	int tmp = 0;
	cin >> tmp >> sx >> sy >> tmp;
	sx ++ ;
	sy ++ ;
	for(int i = 0 ; i <= n + 1 ; i ++ )
		for(int j = 0 ; j <= m + 1 ; j ++ )
		{
			if(i >= 1 && i <= n && j >= 1 && j <= m) cin >> edge[i][j];
			else edge[i][j] = 'X';
			if(edge[i][j] == '*') tx = i, ty = j;
		}
	for(int i = 1 ; i <= n ; i ++ )
	{
		for(int j = 1 ; j <= m ; j ++ )
			if(edge[i][j] != 'X')
				f[i][j].X.l = (edge[i][j - 1] == 'X' ? j : f[i][j - 1].X.l);
		for(int j = m ; j >= 1 ; j -- )
			if(edge[i][j] != 'X')
				f[i][j].X.r = (edge[i][j + 1] == 'X' ? j : f[i][j + 1].X.r);
	}
	for(int j = 1 ; j <= m ; j ++ ) 
	{
		for(int i = 1 ; i <= n ; i ++ )
			if(edge[i][j] != 'X')
				f[i][j].Y.l = (edge[i - 1][j] == 'X' ? i : f[i - 1][j].Y.l);
		for(int i = n ; i >= 1 ; i -- )
			if(edge[i][j] != 'X')
				f[i][j].Y.r = (edge[i + 1][j] == 'X' ? i : f[i + 1][j].Y.r);
	} 
	if(bfs()) cout << "YES";
	else cout << "NO";
	return 0;
}

T2

P6803 [CEOI 2020] 星际迷航

题目背景

原时空限制:0.2s,32m

题目描述

星际联邦由 \(N\) 颗行星组成,分别编号为 \(1 \sim N\)。一些行星间由星际通道相连。通过这些星际通道,飞船可以在短时间内往返于各星球之间。整个星际联邦中恰好有 \(N-1\) 条星际通道,并且通过这些星际通道,任意两颗行星之间均能相互抵达。

除了我们所处的宇宙之外,还有 \(D\) 个平行宇宙,这些平行宇宙是我们的宇宙的完全复刻,它们的行星,星际通道都和我们的完全相同。我们将这些平行宇宙编号为 \(1 \sim D\)(我们的宇宙编号为 \(0\)),记第 \(i\) 个宇宙的第 \(x\) 颗行星为 \(P_{x}^i\)。通过星门,我们可以在这些平行宇宙间穿梭。\(\forall i \in [0,D)\),我们将选择一个 \(A_i\) 和一个 \(B_i\)(要求 \(1 \leq A_i,B_i \leq N\)),在 \(P_{A_i}^i\)\(P_{B_i}^{i+1}\) 之间搭建一个单向(只能从 \(P_{A_i}^i\) 前往 \(P_{B_i}^{i+1}\))星门。

当所有的星门都准备就绪后,联邦星舰 Batthyány 号将会开始它的处女航,它目前正环绕着 \(P_1^0\) 行星。Ágnes 舰长准备和 Gábor 中尉玩这样一个游戏:两个人交替选择星舰接下来前往的目的地,要求该目的地可以通过星际通道或星门直接抵达。他们希望每次前往的星球都是之前未抵达过的。即,如果星舰抵达了 \(P_{x}^i\),他们将不再经过这个星球(但是可以抵达 \(x\) 在其他平行宇宙中的相应星球)。由 Ágnes 舰长作为先手开始游戏,Gábor 中尉作为后手,当一位玩家在他的回合中,不能选择一个合法的目的地时,他就输掉了游戏。

舰长和中尉都是绝对聪明的,他们知道所有星际通道和星门的排布方案,并且他们每次都按照最优方案行动。你需要求出,有多少种布置星门的方案,使得作为先手的 Ágnes 舰长必胜?两种布置星门的方案是不同的,当且仅当存在一个整数 \(i\),使得 \(A_i\)\(B_i\) 不同。

输入格式

第一行两个整数 \(N,D\),分别代表星际联邦拥有的行星数和平行宇宙的数量。

接下来 \(N-1\) 行,每行两个整数 \(u,v\),表示 \(\forall i \in [0,D]\)\(P_u^i,P_v^i\) 之间有星际通道相连。

输出格式

输出能使舰长必胜的星门布置方案数对 \(10^9+7\) 取模的结果。

输入输出样例 #1

输入 #1
3 1
1 2
2 3
输出 #1
4

说明/提示

样例解释

共有 \(3 \times 3=9\) 种本质不同的布置星门的方案,下面列出四种舰长必胜的情况。

子任务

所有数据均满足:\(1 \leq N \leq 10^5\)\(1 \leq D \leq 10^{18}\)\(1 \leq u,v \leq N\)

各子任务的约束条件如下:

子任务编号 分值 约束
\(1\) \(0\) 样例
\(2\) \(7\) \(N=2\)
\(3\) \(8\) \(N \leq 100\)\(D=1\)
\(4\) \(15\) \(N \leq 1000\)\(D=1\)
\(5\) \(15\) \(D=1\)
\(6\) \(20\) \(N \leq 1000\)\(D \leq 10^5\)
\(7\) \(20\) \(D \leq 10^5\)
\(8\) \(15\) 无特殊约束
posted @ 2025-08-18 10:28  tony0530  阅读(12)  评论(0)    收藏  举报