题目描述
如果一个矩阵能够满足所有的行和列都是回文序列,则称这个矩阵为一个完美矩阵。
一个整数序列 a1,a2,…,ak,如果满足对于任何整数 i(1≤i≤k),等式 ai=ak−i+1 均成立,则这个序列是一个回文序列。
给定一个 n×m 的矩阵 a,每次操作可以将矩阵中的某个元素加一或减一,请问最少经过多少次操作后,可以将矩阵 a 变为一个完美矩阵?
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 n 和 m,表示矩阵的大小。
接下来 n 行,每行包含 m 个整数 aij,表示矩阵中的元素。
输出格式
每组数据输出一行,一个答案,表示最少操作次数。
数据范围
1≤T≤10,
1≤n,m≤100,
0≤aij≤109
样例
输入样例:
2
4 2
4 2
2 4
4 2
2 4
3 4
1 2 3 4
5 6 7 8
9 10 11 18
输出样例:
8
42
样例解释
第一组数据可以通过 8 步操作得到以下矩阵:
2 2
4 4
4 4
2 2
第二组数据可以通过 42 步操作得到以下矩阵:
5 6 6 5
6 6 6 6
5 6 6 5
(暴力枚举)
保证回文的话,就需要让四个角落的值相等
求次数最少,那就看这四个数怎么排
第一时间想到的是中间的数(中位数),这样肯定操作的次数最少的
那么是不是其他的数呢?比如平均数
这四个数设为a,b,c,d
设平均数是avg
平均数的答案是(下面的不等式是三角绝对值不等式)
|a−avg|+|b−avg|+|c−avg|+|d−avg||a−avg|+|b−avg|+|c−avg|+|d−avg|
>=|a+b−2∗avg|+|d+c−2∗avg|>=|a+b−2∗avg|+|d+c−2∗avg|
=|2∗avg−(a+b)|+|d+c−2∗avg|=|2∗avg−(a+b)|+|d+c−2∗avg|
>=|d+c−a−b|>=|d+c−a−b|
=d+c−a−b=d+c−a−b
中位数的答案是
|a−b|+|b−b|+|c−b|+|d−b||a−b|+|b−b|+|c−b|+|d−b|
=b−a+c−b+d−b=b−a+c−b+d−b
=d+c−b−a=d+c−b−a
所以中位数的答案小于平均数
中位数更优
时间复杂度 O(n^2)
参考文献
C++ 代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1010;
int t,n,m;
int a[N][N],s[10];
int main()
{
cin>>t;
while(t--)
{
LL res=0;
cin>>n>>m;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
cin>>a[i][j];
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
s[1]=a[i][j];
s[2]=a[i][m-j+1];
s[3]=a[n-i+1][j];
s[4]=a[n-i+1][m-j+1];
sort(s+1,s+1+4);
for(int k = 1; k <= 4; k ++ )
res+=abs(s[k]-s[2]);
}
cout<<res/4<<'\n';
}
return 0;
}
Java代码
import java.io.*;
import java.util.*;
import java.lang.*;
public class Main{
public static void main(String[] args){
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
while(t--!=0)
{
int n=cin.nextInt(),m=cin.nextInt();
int [][] a = new int[n+1][m+1];
int []s= new int [10];
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
a[i][j] = cin.nextInt();
long res=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
s[1] = a[i][j];
s[2] = a[n - i - 1][j];
s[3] = a[i][m - j - 1];
s[4] = a[n - i - 1][m - j - 1];
Arrays.sort(s,1,4);
for(int k = 1; k <= 4; k ++ )
res+=Math.abs(s[k]-s[2]);
}
System.out.println(res/4);
}
return ;
}
}
GO代码
package main
import (
"fmt"
"sort"
)
const N = 110
var a[N][N]int
func abs(x int)int{
if x < 0{
x = -x
}
return x
}
func main(){
var T int
fmt.Scanf("%d",&T)
for ;T > 0;{
T --
var n,m int
fmt.Scanf("%d %d",&n,&m)
for i := 1;i<= n;i ++{
for j := 1;j <= m;j ++{
fmt.Scanf("%d",&a[i][j])
}
}
u,v := n,m
res := 0
for i := 1;i <= u;i ++{
for j := 1;j<=v;j ++{
point := []int{a[i][j],a[i][m - j + 1],a[n - i + 1][j],a[n- i + 1][m - j + 1]}
sort.Slice(point,func(i,j int)bool{
if point[i] < point[j]{
return true
}
return false
})
res += point[3] - point[0] + point[2] - point[1]
}
}
fmt.Println(res/4)
}
}
欢迎留言点赞
嗷嗷嗷~