1 条题解
-
0
题意分析
每秒拍摄一幅黑白二值图像,目标物体在图中对应最大的连续白色区域。要提取每帧该区域的几何中心,再根据前后两帧中心的位移计算平均速度,最后输出 $X$、$Y$ 方向速度。
解题思路
连通域检测:对每帧图像做一次 BFS或DFS,遍历所有白色块,找出最大连通域,记录该域所有像素 $(x,y)$ 坐标累计和与像素数 $N$。
几何中心:中心坐标 $\mathrm{pos}_x(t)=\frac1N\sum x,\quad \mathrm{pos}_y(t)=\frac1N\sum y.$
平均速度:若共有 $2T$ 帧,按公式 $v_x=\frac{1}{T}\sum_{t=0}^{T-1}\bigl(\mathrm{pos}_x(t+T)-\mathrm{pos}_x(t)\bigr),$ $v_y=\frac{1}{T}\sum_{t=0}^{T-1}\bigl(\mathrm{pos}_y(t+T)-\mathrm{pos}_y(t)\bigr).$ 之后按照公式进行计算即可得到答案。
本题代码
#include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN = 256; char mat[MAXN][MAXN+1]; bool vis[MAXN][MAXN]; int dx[4]={1,0,-1,0}, dy[4]={0,1,0,-1}; int main(){ int m,k; while(scanf("%d%d",&m,&k)==2 && (m||k)){ vector<double> cx, cy; while(true){ // 读入一幅图 for(int i=0;i<k;i++) scanf("%s", mat[i]); // 标记结束符号 char sep = getchar(); while(sep!='\n') sep=getchar(); // 计算最大连通域中心 memset(vis,0,sizeof vis); int bestCnt=0; double sumX=0,sumY=0; for(int y=0;y<k;y++)for(int x=0;x<m;x++){ if(!vis[y][x] && mat[y][x]=='x'){ int cnt=0; double sx=0,sy=0; queue<pair<int,int>> q; q.push({y,x}); vis[y][x]=1; while(!q.empty()){ auto [cy0,cx0]=q.front(); q.pop(); cnt++; sx+=cx0; sy+=cy0; for(int d=0;d<4;d++){ int ny=cy0+dy[d], nx=cx0+dx[d]; if(ny>=0&&ny<k&&nx>=0&&nx<m && !vis[ny][nx] && mat[ny][nx]=='x'){ vis[ny][nx]=1; q.push({ny,nx}); } } } if(cnt>bestCnt){ bestCnt=cnt; sumX=sx; sumY=sy; } } } cx.push_back(sumX/bestCnt); cy.push_back(sumY/bestCnt); // 判断分隔符或结束符 // 回读一行 m 个字符 char line[MAXN+1]; fgets(line, m+2, stdin); if(line[0]=='=') break; } int frames = cx.size(); int T = frames/2; double vx=0, vy=0; for(int i=0;i<T;i++){ vx += cx[i+T]-cx[i]; vy += cy[i+T]-cy[i]; } vx = vx / T; vy = vy / T; printf("%.2f %.2f\n", vx, vy); } return 0; }
- 1
信息
- ID
- 328
- 时间
- 5000ms
- 内存
- 10MiB
- 难度
- 10
- 标签
- 递交数
- 5
- 已通过
- 1
- 上传者