1 条题解
-
0
自动搬运
来自洛谷,原作者为

yqr123YQR
汝若将降世, 切忌罪行恶果,唯使光明降临搬运于
2025-08-24 22:27:27,当前版本为作者最后更新于2024-01-31 20:16:11,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
稍显幼稚的小游戏轻松快乐简单小模拟,考察基本广搜 / 深搜判连通块。题意
每次打破一个方格上的
矿物,然后使单独的“腾空”连通块一直下落,直至与其他连通块相接 / 落至地面。请模拟此操作,矩阵大小 ,。分析
这有什么好分析的?唯一一点点问题在于,题中遵循真实物理定律的“下落”。
- 确定下落的是哪个块
由于 数据范围与约定 中 “保证在任何时间点都不会有两个或两个以上的碎块群同时落下”,我们可以在被破坏的方格四周轻松找出两个连通块,每个都执行一次下落操作即可。
- 下落的实现
简单粗暴地,对于每个连通块中的点,往下依次找,直到碰到地面 / 其他连通块,最后整体下移。
代码
#include<stdio.h> #include<queue> using namespace std; const int maxn = 100; int r, c, n, cnt, vis[maxn + 5][maxn + 5], dx[4] = {0, 0, -1, 1}, dy[4] = {-1, 1, 0, 0}; char mp[maxn + 5][maxn + 5]; bool isstone(int x, int y) {return x <= r && x && y <= c && y && mp[x][y] == 'x';} struct node {int x, y;}; void bfs(int sx, int sy, int tag)//对点 (sx,sy) 所在连通块打上 tag 的标记 { queue<node> q; q.push({sx, sy}); vis[sx][sy] = tag; while(!q.empty()) { node t = q.front(); q.pop(); for(int i = 0; i < 4; i++) { int nx = t.x + dx[i], ny = t.y + dy[i]; if(isstone(nx, ny) && !vis[nx][ny]) vis[nx][ny] = tag, q.push({nx, ny}); } } } void calc()//重新计算每个点所属连通块 { for(int i = 1; i <= r; i++) for(int j = 1; j <= c; j++) vis[i][j] = 0; cnt = 0; for(int i = 1; i <= r; i++) for(int j = 1; j <= c; j++) if(isstone(i, j) && !vis[i][j]) bfs(i, j, ++cnt); } void down(int tag)//下落标记为 tag 的连通块 { int ans = r + 1; for(int i = 1; i <= r; i++) { for(int j = 1; j <= c; j++) { if(vis[i][j] == tag) { int dis = 0; while(dis <= r - i && (mp[i + dis][j] == '.' || vis[i + dis][j] == tag)) dis++; ans = ans < --dis? ans: dis; } } } for(int i = r; i > ans; i--) { for(int j = 1; j <= c; j++) { if(vis[i - ans][j] == tag) mp[i - ans][j] = '.', mp[i][j] = 'x'; } } } void goal(int height, int side)//射出木棍 { int fst = -1; for(int i = side == 1? 1: c; i && i <= c; i += side) { if(mp[height][i] == 'x') { fst = i; break; } } if(!~fst) return; mp[height][fst] = '.'; calc(); // for(int i = 1; i <= r; i++) // { // for(int j = 1; j <= c; j++) printf("%d ", vis[i][j]); // puts(""); // } int id = -1; for(int i = 0; i < 4; i++) { int nx = height + dx[i], ny = fst + dy[i]; if(isstone(nx, ny)) { if(~id && id != vis[nx][ny]) { // puts("ff"); down(id), down(vis[nx][ny]); break; } id = vis[nx][ny]; } } } int main() { scanf("%d%d", &r, &c); for(int i = 1; i <= r; i++) scanf("%s", mp[i] + 1); calc(); scanf("%d", &n); for(int i = 1, height; i <= n; i++) { scanf("%d", &height); height = r - height + 1; goal(height, (i & 1)? 1: -1); // puts("begin:"); // for(int ii = 1; ii <= r; ii++) puts(mp[ii] + 1); // puts("end."); } for(int i = 1; i <= r; i++) puts(mp[i] + 1); return 0; }
- 1
信息
- ID
- 5814
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者