Codeforces Round #531 (Div. 3) F. Elongated Matrix (状压+记搜)

F. Elongated Matrix

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a matrix aa, consisting of nn rows and mm 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,…,snms1,s2,…,snm.

The traversal is kk-acceptable if for all ii (1≤i≤nm−11≤i≤nm−1) |si−si+1|≥k|si−si+1|≥k.

Find the maximum integer kk such that there exists some order of rows of matrix aa that it produces a kk-acceptable traversal.

Input

The first line contains two integers nn and mm (1≤n≤161≤n≤16, 1≤m≤1041≤m≤104, 2≤nm2≤nm) — the number of rows and the number of columns, respectively.

Each of the next nn lines contains mm integers (1≤ai,j≤1091≤ai,j≤109) — the description of the matrix.

Output

Print a single integer kk — the maximum number such that there exists some order of rows of matrix aa that it produces an kk-acceptable traversal.

Examples

input

Copy

4 2
9 9
10 8
5 3
4 3

output

Copy

5

input

Copy

2 4
1 2 3 4
10 3 7 3

output

Copy

0

input

Copy

6 1
3
6
2
5
1
4

output

Copy

3

Note

In the first example you can rearrange rows as following to get the 55-acceptable traversal:

5 3
10 8
4 3
9 9

Then the sequence ss will be [5,10,4,9,3,8,3,9][5,10,4,9,3,8,3,9]. Each pair of neighbouring elements have at least k=5k=5 difference between them.

In the second example the maximum k=0k=0, any order is 00-acceptable.

In the third example the given order is already 33-acceptable, you can leave it as it is.

题意:

给你一个n*m(n<=16,m<=1e4)的矩阵,你可以把行的顺序重新排列,使重新排列后从a11,a21,...,an1,a12,a22,...,anm序列中相邻两个数的差的绝对值的最小值最大。

思路:最小值最大,第一反应二分。但是一看这题数据范围,显然首先是用两个数组预处理出两行之间的"距离"(即对应同一列的值的差的绝对值的最小值)和第j行为第一行,第i行为最后一行的“首尾距离”。

然后 一看n<=16,可以状压。怎么状压呢?显然是第i为为0表示第i行还未使用,1就是使用过了。然后总结果还与第一行、最后一行是哪两行有关,于是就可以记忆化搜索了。

dp[zt][dn][d1]表示状态zt时,第1行为原数组第d1行,当前行为原数组第dn行时答案的最大值。

则dfs中遍历i=0~n-1,依次枚举第i行作为当前最后一行的时候的结果。

注意:

确定第一行时,要特判一下,因为初始距离是inf,用“距离”数组结果会是0。特判的时候要用当前最后一行(因为第一行会因为你的确定而改变,好好理解一下这句话)。

最后填完的时候注意答案就是“首尾距离”,需要特判一下。

具体细节见代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=25;
const int maxm=10010;
int n,m,k;
int a[maxn][maxm];
int dis[maxn][maxn],dis2[maxn][maxn];
int dp[70000][maxn][maxn];
int ans,tmp,cnt;
int dfs(int zt,int dn,int d1)
{
    int &res=dp[zt][dn][d1];
    if(res!=-1) return res;
    int ct=0,ma=-inf,tmp;
    for(int i=0;i<n;i++)
    {
        if(zt&(1<<i)) continue;
        ct++;
        if(dn!=20) tmp=dis[dn][i];//dn!!!
        else {d1=i;tmp=inf;}
        tmp=min(tmp,dfs(zt|(1<<i),i,d1));
        ma=max(ma,tmp);
    }
    if(!ct) ma=dis2[dn][d1];
    res=ma;
    return res;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    for(int j=0;j<m;j++)
    scanf("%d",&a[i][j]);
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        dis[i][j]=dis2[i][j]=inf;
        for(int k=0;k<m;k++)
        {
            dis[i][j]=min(dis[i][j],abs(a[i][k]-a[j][k]));
            if(k<m-1) dis2[i][j]=min(dis2[i][j],abs(a[i][k]-a[j][k+1]));
        }
    }
    memset(dp,-1,sizeof(dp));
    int ans=dfs(0,20,20);
    printf("%d\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值