1067. 最匹配的矩阵
题目描述
给定一个m*n的矩阵A和r*s的矩阵B,其中0<r<=m,0<s<=n,A、B所有元素值都是小于100的正整数。求A中一个大小为r*s的子矩阵C,使得B和C的对应元素差值的绝对值之和最小,这时称C为最匹配的矩阵。如果有多个子矩阵同时满足条件,选择子矩阵左上角元素行号小者,行号相同时,选择列号小者。
输入
第一行是m和n,以一个空格分开。
之后m行每行有n个整数,表示A矩阵中的各行,数与数之间以一个空格分开。
第m+2行为r和s,以一个空格分开。
之后r行每行有s个整数,表示B矩阵中的各行,数与数之间以一个空格分开。
输出
输出矩阵C,一共r行,每行s个整数,整数之间以一个空格分开。
样例输入
3 3
3 4 5
5 3 4
8 2 4
2 2
7 3
4 9
样例输出
4 5
3 4
数据范围限制
1<=m<=100,1<=n<=100
C++代码
#include <iostream>
#include <cassert> // assert()
#include <cmath> // abs()
using namespace std;
const int max_rows = 100; // maximum rows
const int max_cols = 100; // maximum columns
class Result
{
public:
int m_sum; // sum of the absolute values of the elements differences
int m_row; // row of Matrix A
int m_col; // column of Matrix B
Result() { m_sum = 0; m_row = 0; m_col = 0; };
Result(int sum, int row, int col): m_sum(sum),m_row(row),m_col(col) {};
bool operator < (Result &result)
{
if (m_sum == result.m_sum)
{
if (m_row == result.m_row)
{
return m_col < result.m_col;
}
else
{
return m_row < result.m_row;
}
}
else
{
return m_sum < result.m_sum;
}
}
};
class Matrix
{
public:
int m_rows; // number of rows
int m_cols; // number of columns
int m_elems[max_rows+1][max_cols+1]; // row, col starts from 1
Matrix(int rows, int cols): m_rows(rows), m_cols(cols) {};
};
class NOI1067
{
public:
Result getMinSumOfAbsValues(Matrix& bigMatrix, Matrix& smallMatrix);
void printSmallMatrix(Result& result, Matrix& bigMatrix, Matrix& smallMatrix);
private:
const static int max_value = 100; // maximum value of Matrix element
Result calcSumOfAbsValues(int row,int col,Matrix& bigMatrix,Matrix& smallMatrix);
};
Result NOI1067::calcSumOfAbsValues(int row, int col, Matrix& bigMatrix, Matrix& smallMatrix)
{
Result result(0, row, col);
for(int i=1; i<=smallMatrix.m_rows; i++)
{
for(int j=1; j<=smallMatrix.m_cols;j++)
{
result.m_sum += abs(bigMatrix.m_elems[row+i-1][col+j-1] - \
smallMatrix.m_elems[i][j]);
}
}
return result;
}
Result NOI1067::getMinSumOfAbsValues(Matrix& bigMatrix, Matrix& smallMatrix)
{
Result result;
Result minResult(max_value*smallMatrix.m_rows*smallMatrix.m_cols, 0, 0);
for(int row=1; row+smallMatrix.m_rows<=bigMatrix.m_rows+1; row++)
{
for (int col=1; col+smallMatrix.m_cols<=bigMatrix.m_cols+1; col++)
{
result = calcSumOfAbsValues(row, col, bigMatrix, smallMatrix);
if (result < minResult)
{
minResult = result;
}
}
}
return minResult;
}
void NOI1067::printSmallMatrix(Result& result, Matrix& bigMatrix, Matrix& smallMatrix)
{
for(int i=1; i<=smallMatrix.m_rows; i++)
{
for(int j=1; j<=smallMatrix.m_cols; j++)
{
cout << bigMatrix.m_elems[result.m_row+i-1][result.m_col+j-1] << " ";
}
cout << endl;
}
}
int main()
{
int m, n;
cin >> m >> n;
assert(m>=1 && m<=max_rows);
assert(n>=1 && n<=max_cols);
Matrix matrixA(m, n);
for(int row=1; row<=m; row++)
{
for(int col=1; col<=n; col++)
{
cin >> matrixA.m_elems[row][col];
}
}
int r, s;
cin >> r >> s;
Matrix matrixB(r, s);
for(int row=1; row<=r; row++)
{
for(int col=1; col<=s; col++)
{
cin >> matrixB.m_elems[row][col];
}
}
NOI1067 noi1067;
Result minResult = noi1067.getMinSumOfAbsValues(matrixA, matrixB);
noi1067.printSmallMatrix(minResult, matrixA, matrixB);
return 0;
}