P6370 [COCI2006-2007#6] KAMEN 题解

P6370

暴力是很容易的,可以直接搜索。

发现可以直接对暴力进行优化。每次有一个地方变为 O 后,重构代价太大,设这个坐标为 (i,j),同时维护一个类型为 pair<int, int>to 数组表示将球放在第 i 列第一行的时候,最后到达的位置。再用一个 pathi 记录下从第一行第 i 列出发的路径以及一个 visi,j,k 表示第 i 行第 j 列是否能通过放在第 k 列到达,如果可以,记录的就是再 path 中的下标。然后发现只有 (i,j) 附近的八个格子可能会受影响,剪枝一下,即判断 (i,j) 之前是否在 (i,j) 所经过的路径上即可。这样实际上就是根据路径上的前缀不变对暴力进行的优化。

为什么这样的时间复杂度是对的呢?因为每次 toi 的行数要么增加 Δ,要么 1,所以均摊下来的时间复杂度就是对的了。

但是这样空间是 O(rc2),无法通过。发现每次的 O 所在的位置一定是所有路径的终点,所以就不用记录 vis 数组了,因为每次操作一定是 path 的栈顶,直接 pop 即可。

时间复杂度:O(rc2)

空间复杂度:O(rc)

代码:

mt19937_64 rng(35);
constexpr int N = 3e4 + 10;
int n, m, q;
int tp[35], pa[35][N];
char ch[N][35];
void work(int x) {
	while(1) {
		int y = pa[x][tp[x]];
		if(ch[tp[x]][y] == 'O') --tp[x];
		else if(tp[x] == n) break;
		else if(ch[tp[x] + 1][y] == 'X') break;
		else if(ch[tp[x] + 1][y] == '.') pa[x][++tp[x]] = y;
		else if(y > 1 && ch[tp[x]][y - 1] == '.' && ch[tp[x] + 1][y - 1] == '.') pa[x][++tp[x]] = y - 1;
		else if(y < m && ch[tp[x]][y + 1] == '.' && ch[tp[x] + 1][y + 1] == '.') pa[x][++tp[x]] = y + 1;
		else break;
	}
	ch[tp[x]][pa[x][tp[x]]] = 'O';
}
int main() {
	ios :: sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n >> m;
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
			cin >> ch[i][j];
	for(int i = 1; i <= m; ++i)
		pa[i][tp[i] = 0] = i;
	cin >> q;
	for(int qi = 1; qi <= q; ++qi) {
		int x;
		cin >> x;
		work(x);
	}
	for(int i = 1; i <= n; ++i) {
		for(int j = 1; j <= m; ++j)
			cout << ch[i][j];
		cout << "\n";
	}
	return 0;
}
posted @   Pengzt  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示