1 条题解

  • 0
    @ 2025-5-6 13:43:57

    题意分析

    每秒拍摄一幅黑白二值图像,目标物体在图中对应最大的连续白色区域。要提取每帧该区域的几何中心,再根据前后两帧中心的位移计算平均速度,最后输出 $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
    上传者