最匹配的矩阵

GitHub跳转原题关系图返回列表

枚举大矩阵中所有可放置位置,比较对应元素绝对差之和。

OJ: noi_openjudge

题目 ID: ch0112-04

难度:普及-

标签:枚举矩阵模拟python

日期: 2026-07-30 23:01

题意

在大矩阵中选择一个与给定小矩阵同尺寸的子矩阵,使对应元素差的绝对值和最小;并按左上角行、列优先打破平局。

思路

按行优先、列次优先枚举所有左上角位置,双层循环累加对应元素的绝对差。仅在严格更小时更新答案,因此相等时会自然保留先枚举到的行列更小的位置。最后按记录的位置切片输出。

代码

Python代码

python
row_count, column_count = map(int, input().split())
matrix = [list(map(int, input().split())) for _ in range(row_count)]
pattern_rows, pattern_columns = map(int, input().split())
pattern = [list(map(int, input().split())) for _ in range(pattern_rows)]

best_position = (0, 0)
best_difference = float("inf")

for top in range(row_count - pattern_rows + 1):
    for left in range(column_count - pattern_columns + 1):
        difference = sum(
            abs(matrix[top + row][left + column] - pattern[row][column])
            for row in range(pattern_rows)
            for column in range(pattern_columns)
        )
        if difference < best_difference:
            best_difference = difference
            best_position = (top, left)

top, left = best_position
for row in matrix[top : top + pattern_rows]:
    print(*row[left : left + pattern_columns])

C++代码

cpp
#include<iostream>
#include<cstdio>
using namespace std;

int A[105][105];
int B[105][105];
int m, n, r, s;

void init() {

    scanf("%d%d",&m,&n);
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d",&A[i][j]);
    scanf("%d%d",&r,&s);
    for (int i = 1; i <= r; i++)
        for (int j = 1; j <= s; j++)
            scanf("%d",&B[i][j]);
}

int _abs(int a){
    return a<0 ? -a:a;
}

int check(int x,int y){
    int sum = 0;
    for (int i = 1; i <= r; i++)
        for (int j = 1; j <= s; j++)
            sum += _abs(B[i][j] - A[x+i-1][y+j-1]);
    return sum;
}

int main() {

    init();

    int x, y, max_ = 10000000,maxx,maxy;
    for (y = 1; y <= m-r+1; y++)
        for (x = 1; x <= n-s+1; x++) { //meiju
            int t = check(y,x);
            if ( t < max_) {
                max_ = t;
                maxx = y;
                maxy = x;
            }
        }

    for(int i =maxx;i <= maxx+r-1  ;i++){
        for(int j = maxy;j <=maxy+s-1;j++){
            printf("%d ",A[i][j]);
        }
        printf("\n");
    }
    return 0;
}

复杂度

时间复杂度为 O((mr+1)(ns+1)rs)O((m-r+1)(n-s+1)rs),空间复杂度为 O(mn)O(mn)

总结

枚举顺序与“平局选最小坐标”的规则一致时,更新条件只需使用严格小于。