[信息与未来 2023] 图像重建

· · 题解

题意理解

给出两张图,每张图的第一行两个数表示行列数量,两张图之间空一行。

两张图可以任意平移,求平移后完全重合的最多格点数。

思路阐述

直接暴力寻找,先固定一张图,再将另一张的四个角对上来,按照对上来这张图的方向遍历每一个点。

如图:蓝色点是基础点,黑色是基础图,红色是另一张图,绿色是遍历方向。

左上角

右下角

左下角

右上角

具体方法:遍历第一张图的每一个点,再以这个点为基础,将第二张图的左上角、左下角、右上角、右下角分别对应上去搜索。当然还要以第二张图为基础用同样的方式再遍历一次。

优化:因为两张图必须完全重合才在答案考虑范围内,所以只要有一格不对应即可直接退出这种情况。

代码呈现

#include <bits/stdc++.h>
using namespace std;

int a,b;//第一张图的行列
int c,d;//第二张
bool mp1[55][55];//图一
bool mp2[55][55];//图二
int x;//辅助输入
int ans,cnt;//计数
bool f;//标记是否在重合范围内各个格子都相同
string s;//吃掉中间的空行

signed main(){

    scanf("%d%d",&a,&b);
    for (int i=1;i<=a;i++)
        for (int j=1;j<=b;j++){
            scanf("%d",&x);
            if (x) mp1[i][j]=1;
        }
    getline(cin,s);//吃掉中间的空行
    scanf("%d%d",&c,&d);
    for (int i=1;i<=c;i++)
        for (int j=1;j<=d;j++){
            scanf("%d",&x);
            if (x) mp2[i][j]=1;
        }
    for (int i=1;i<=a;i++)
        for (int j=1;j<=b;j++){//遍历图一
            cnt=0;
            f=1;//初始化变量
            for (int k=1;k<=c;k++){
                if (i+k>a) break;//注意遍历图二时不要超图一范围
                for (int l=1;l<=d;l++){//对应左上角
                    if (j+l>b) break;
                    if (mp1[i+k][j+l]==mp2[k][l]){
                        cnt++;//相同
                    }
                    else{
                        f=0;//不同,标记
                        break;//退出
                    }
                }
                if (!f) break;//有不同的,退出
            }
            if (f) ans=max(ans,cnt);//没有问题,取最大值

            cnt=0;
            f=1;
            for (int k=c;k>=1;k--){
                if (i-(c-k)<1) break;
                for (int l=d;l>=1;l--){//右下角
                    if (j-(d-l)<1) break;
                    if (mp1[i-(c-k)][j-(d-l)]==mp2[k][l]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);

            cnt=0;
            f=1;
            for (int k=c;k>=1;k--){
                if (i-(c-k)<1) break;
                for (int l=1;l<=d;l++){//右上角
                    if (j+l>b) break;
                    if (mp1[i-(c-k)][j+l]==mp2[k][l]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);

            cnt=0;
            f=1;
            for (int k=1;k<=c;k++){
                if (i+k>a) break;
                for (int l=d;l>=1;l--){//左下角
                    if (j-(d-l)<1) break;
                    if (mp1[i+k][j-(d-l)]==mp2[k][l]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);
        }

    for (int i=1;i<=c;i++)
        for (int j=1;j<=d;j++){//以第二张图为基础的遍历
            cnt=0;
            f=1;
            for (int k=1;k<=a;k++){
                if (i+k>c) break;
                for (int l=1;l<=b;l++){
                    if (j+l>d) break;
                    if (mp1[k][l]==mp2[k+i][l+j]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);

            cnt=0;
            f=1;
            for (int k=a;k>=1;k--){
                if (i-(a-k)<1) break;
                for (int l=b;l>=1;l--){
                    if (j-(b-l)<1) break;
                    if (mp1[k][l]==mp2[i-(a-k)][j-(b-l)]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);

            cnt=0;
            f=1;
            for (int k=1;k<=a;k--){
                if (i+k>c) break;
                for (int l=b;l>=1;l--){
                    if (j-(b-l)<1) break;
                    if (mp1[k][l]==mp2[i+k][j-(b-l)]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);

            cnt=0;
            f=1;
            for (int k=a;k>=1;k--){
                if (i-(a-k)<1) break;
                for (int l=1;l<=b;l--){
                    if (j+l>d) break;
                    if (mp1[k][l]==mp2[i-(a-k)][j+l]){
                        cnt++;
                    }
                    else{
                        f=0;
                        break;
                    }
                }
                if (!f) break;
            }
            if (f) ans=max(ans,cnt);
        }
    printf("%d",ans);//输出
    return 0;

}

希望可以帮到各位大佬。