F. Elongated Matrix
把n个行当成一个个点,点之间的距离就是相同位置差值的最大值
- 枚举起点
- 以这个起点出发求状压dp,dp[S][i] 代表最后到达的点是i,状态是S
- 枚举终点
#include <algorithm>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N = 16;
const int M = 10000;
const int INF = 1000000000;
int aa[N][M], kk[N][N], dp[1 << N][N];
int main() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf("%d", &aa[i][j]);
for (int i1 = 0; i1 < n; i1++)
for (int i2 = i1 + 1; i2 < n; i2++) {
int k = INF;
for (int j = 0; j < m; j++)
k = min(k, abs(aa[i1][j] - aa[i2][j]));
kk[i1][i2] = kk[i2][i1] = k;
}
int ans = 0;
for (int s = 0; s < n; s++) {
for (int b = 0; b < 1 << n; b++)
fill_n(dp[b], n, 0);
dp[1 << s][s] = INF;
for (int b = 0; b < 1 << n; b++)
for (int i_ = 0; i_ < n; i_++)
if (dp[b][i_])
for (int i = 0; i < n; i++)
if (!(b & 1 << i))
dp[b | 1 << i][i] = max(dp[b | 1 << i][i], min(dp[b][i_], kk[i_][i]));
for (int i = 0; i < n; i++) {
int k = dp[(1 << n) - 1][i];
for (int j = 0; j + 1 < m; j++)
k = min(k, abs(aa[i][j] - aa[s][j + 1]));
ans = max(ans, k);
}
}
printf("%d\n", ans);
return 0;
}