You are given a grid consisting of n rows each of which is dived into m columns. The rows are numbered from 1 to n from top to bottom, and the columns are numbered from 1 to m from left to right. Each cell is identified by a pair (x, y), which means that the cell is located in the row x and column y.
Your goal is to delete a row x (1 < x < n) and a column y (1 < y < m), after this the matrix will be divided into 4 parts. Let us define the beauty of each part as the maximum value inside it. Your task is to choose x and y such that the difference between the largest and smallest beauties is as minimal as possible. Can you?
Input
The first line contains an integer T (1 ≤ T ≤ 100) specifying the number of test cases.
The first line of each test case contains two integers n and m (3 ≤ n, m ≤ 500), specifying the grid size, in which n is the number of rows and m is the number of columns.
Then n lines follow, each line contains m integers, giving the grid. All values in the grid are between 1 and 109 (inclusive).
Output
For each test case, print a single line containing the minimum difference between the largest and smallest beauties after dividing the matrix into 4 parts.
input
2 3 3 9 5 8 3 4 1 6 2 7 4 4 22 7 3 11 3 1 8 9 5 2 4 3 13 5 6 9
output
3 13
题意:给你n行m列的矩阵,你可以删去非边缘的一行一列,将矩阵分成四个部分,每个部分所有数的最大数为这一部分的val,再定义差值为四个部分中val最大的部分减val最小的部分为差值,问你删去一行一列之后最小的差值是到多少。
题解:预处理四个方向的最大值,做到删除一行一列之后可以O(1)查询出每一部分的最大值。思路类似前缀和。如删去第3行第3列,那么左上角那一块的最大值为从1,1点到2,2点这些数的最大值。其他三个角同理,右上角那一块是从右上角到点2,4的所有点的最大值。以此类推。。。
所以就建四个数组分别表示 。
从左上角往右下角推的最大值,如dp[2][2]为从1,1到2,2这些数中的最大值。
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define ll long long
int dp[505][505][5],mp[505][505],co[5];
int main(){
//鸡尾酒QAQ
int m,n,t;
cin>>t;
while(t--){
cin>>n>>m;
int ans=1e9;
memset(mp,0,sizeof mp);
memset(dp,0,sizeof dp);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&mp[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
dp[i][j][1]=max(dp[i-1][j][1],max(dp[i][j-1][1],mp[i][j]));
for(int i=1;i<=n;i++)
for(int j=m;j>=1;j--)
dp[i][j][2]=max(dp[i-1][j][2],max(dp[i][j+1][2],mp[i][j]));
for(int i=n;i>=1;i--)
for(int j=1;j<=m;j++)
dp[i][j][3]=max(dp[i+1][j][3],max(dp[i][j-1][3],mp[i][j]));
for(int i=n;i>=1;i--)
for(int j=m;j>=1;j--)
dp[i][j][4]=max(dp[i+1][j][4],max(dp[i][j+1][4],mp[i][j]));
for(int i=2;i<=n-1;i++)
for(int j=2;j<=m-1;j++){
co[0]=dp[i-1][j-1][1];co[1]=dp[i-1][j+1][2];co[2]=dp[i+1][j-1][3];co[3]=dp[i+1][j+1][4];
sort(co,co+4);
ans=min(ans,co[3]-co[0]);
}
cout<<ans<<endl;
}
}
中间四个for循环预处理四个角往中间推的最大值,最后就是枚举删除一行一列能获得的差值,寻找最小差值。