传送门:https://codeforces.com/contest/1102/problem/F
You are given a matrix a, consisting of n rows and m columns. Each cell contains an integer in it.
You can change the order of rows arbitrarily (including leaving the initial order), but you can’t change the order of cells in a row. After you pick some order of rows, you traverse the whole matrix the following way: firstly visit all cells of the first column from the top row to the bottom one, then the same for the second column and so on. During the traversal you write down the sequence of the numbers on the cells in the same order you visited them. Let that sequence be s1,s2,…,snm.
The traversal is k-acceptable if for all i (1≤i≤nm−1) |si−si+1|≥k.
Find the maximum integer k such that there exists some order of rows of matrix a that it produces a k-acceptable traversal.
Input
The first line contains two integers n and m (1≤n≤16, 1≤m≤104, 2≤nm) — the number of rows and the number of columns, respectively.
Each of the next n lines contains m integers (1≤ai,j≤109) — the description of the matrix.
Output
Print a single integer k — the maximum number such that there exists some order of rows of matrix a that it produces an k-acceptable traversal.
Examples
input
4 2
9 9
10 8
5 3
4 3
output
5
题意:给一个n*m的数字矩阵,可以随意交换任意两行的顺序,然后按列顺序遍历整个矩阵,得到一个长度为nm的序列。要求使任意交换行之后的矩阵得到的序列中相邻两个数差值的最小值最大。
解法:忽略行,把每一行看做一个单独的节点,如果i行与j行相邻,那么他们之间有一个权值,大小为min(abs(a[i][k] - a[j][k])), k表示列,取值为1~m;对于第1行和第n行,他们之间也有权值,假如让i行作为第1行,j行作为第n行,那么他们之间的权值就为min(abs(a[i][k], a[j][k+1])), k的取值为1~m-1 。
如果我们忽略第1行与第n行之间的权值,那么这个题就变成了求最小哈密顿距离,直接dp就好。考虑第1行与第n行之间的权值,就需要枚举第1行和第n行。
/*
c1[i][j]存的是i,j行相邻时的权值
c2[i][j]存的是当第i行作为最后一行,j行作为第一行时的权值
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 5;
const int inf = 0x3f3f3f3f;
int a[17][maxn], c1[17][17], c2[17][17], dp[1 << 17][17];
int n, m;
int cal(int mask, int u)
{
if(dp[mask][u] != -1) return dp[mask][u];
dp[mask][u] = 0;
for(int v = 0; v < n; v++){
if(v == u) continue;
if((mask >> v) & 1)
dp[mask][u] = max(dp[mask][u], min(c1[v][u], cal(mask ^ (1 << u), v)));
}
return dp[mask][u];
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++) cin >> a[i][j];
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
c1[i][j] = c2[i][j] = inf;
for(int k = 0; k < m; k++) c1[i][j] = min(c1[i][j], abs(a[i][k] - a[j][k]));
for(int k = 0; k < m - 1; k++) c2[i][j] = min(c2[i][j], abs(a[i][k] - a[j][k + 1]));
}
}
int ans = 0;
// 这里就是在枚举第1行和第n行
for(int i=0;i<n;i++){
memset(dp,-1,sizeof dp);
for(int j=0;j<n;j++)
dp[1<<j][j]=i==j?inf:0; // 这里的inf就保证了i一定是第1行
for(int j=0;j<n;j++)
ans=max(ans,min(c2[j][i],cal((1<<n)-1,j)));
}
cout << ans << '\n';
return 0;
}