将 3 X 3 矩阵转换为幻方的最低成本
魔方是从 1 到 n2 的不同元素的 anxn 矩阵,其中任何行、列或对角线的总和始终等于相同的数字。
考虑包含范围 [1, 9] 内的整数的 3 X 3 矩阵s 。我们可以将 [1, 9] 范围内的任何数字a转换为任何其他数字b成本为|a – b| .
给定s ,通过更改其零个或多个数字以最小的成本将其转换为幻方。任务是找到最小成本。
注意:生成的矩阵必须包含 [1, 9] 范围内的不同整数。
例子:
Input : mat[][] = { { 4, 9, 2 },
{ 3, 5, 7 },
{ 8, 1, 5 }};
Output : 1
Given matrix s is not a magic square. To convert
it into magic square we change the bottom right
value, s[2][2], from 5 to 6 at a cost of | 5 - 6 |
= 1.
Input : mat[][] = { { 4, 8, 2 },
{ 4, 5, 7 },
{ 6, 1, 6 }};
Output : 4
这个想法是找到所有 3 X 3 幻方,并为每个幻方计算将mat更改为已知幻方的成本。结果是这些成本中最小的。
我们知道s总是 3 X 3。对于 3 X 3 矩阵,有 8 个可能的幻方。
有两种方法可以解决这个问题:
因此,通过检查整数 1、2、3、.....、9 的所有排列来计算所有 8 个幻方,并且对于每一个,如果从左上角开始将排列插入到正方形中,则检查它是否形成幻方角落。
下面是这种方法的 C++ 实现:
C++
#include
using namespace std;
// Return if given vector denote the magic square or not.
bool is_magic_square(vector v)
{
int a[3][3];
// Convert vector into 3 X 3 matrix
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
a[i][j] = v[3 * i + j];
int s = 0;
for (int j = 0; j < 3; ++j)
s += a[0][j];
// Checking if each row sum is same
for (int i = 1; i <= 2; ++i) {
int tmp = 0;
for (int j = 0; j < 3; ++j)
tmp += a[i][j];
if (tmp != s)
return 0;
}
// Checking if each column sum is same
for (int j = 0; j < 3; ++j) {
int tmp = 0;
for (int i = 0; i < 3; ++i)
tmp += a[i][j];
if (tmp != s)
return 0;
}
// Checking if diagonal 1 sum is same
int tmp = 0;
for (int i = 0; i < 3; ++i)
tmp += a[i][i];
if (tmp != s)
return 0;
// Checking if diagonal 2 sum is same
tmp = 0;
for (int i = 0; i < 3; ++i)
tmp += a[2 - i][i];
if (tmp != s)
return 0;
return 1;
}
// Generating all magic square
void find_magic_squares(vector >& magic_squares)
{
vector v(9);
// Initialing the vector
for (int i = 0; i < 9; ++i)
v[i] = i + 1;
// Producing all permutation of vector
// and checking if it denote the magic square or not.
do {
if (is_magic_square(v)) {
magic_squares.push_back(v);
}
} while (next_permutation(v.begin(), v.end()));
}
// Return sum of difference between each element of two vector
int diff(vector a, vector b)
{
int res = 0;
for (int i = 0; i < 9; ++i)
res += abs(a[i] - b[i]);
return res;
}
// Wrapper function
int wrapper(vector v)
{
int res = INT_MAX;
vector > magic_squares;
// generating all magic square
find_magic_squares(magic_squares);
for (int i = 0; i < magic_squares.size(); ++i) {
// Finding the difference with each magic square
// and assigning the minimum value.
res = min(res, diff(v, magic_squares[i]));
}
return res;
}
// Driven Program
int main()
{
// Taking matrix in vector in rowise to make
// calculation easy
vector v;
v.push_back(4);
v.push_back(9);
v.push_back(2);
v.push_back(3);
v.push_back(5);
v.push_back(7);
v.push_back(8);
v.push_back(1);
v.push_back(5);
cout << wrapper(v) << endl;
return 0;
}
输出:
1