zoukankan      html  css  js  c++  java
  • Codeforces Round #531 (Div. 3) F. Elongated Matrix(状压DP)

    F. Elongated Matrix

    题目链接:https://codeforces.com/contest/1102/problem/F

    题意:

    给出一个n*m的矩阵,现在可以随意交换任意的两行,最后从上到下,从左到右形成一个序列s1,s2.....snm,满足对于任意相邻的两个数,它们差的绝对值的最大值为k。

    现在问怎么交换行与行,可以使得最后的这个k最大。

    题解:

    人生中第一道状压dp~其实还是参考了这篇博客:https://blog.csdn.net/CSDNjiangshan/article/details/86239183?tdsourcetag=s_pctim_aiomsg

    这篇博客思路已经说得很清楚了,我就说下注意的几点吧:

    行和列的下标是从0开始的,这是为了适应二进制操作,结合代码想想就知道了,我一开始就是这里没注意;

    还有就是n=1时的特判,代码不能很好地处理这种情况,这时横坐标是0,不是1....

    其余的照着思路写就是了。

    我还有一个谜之问题,就是我先枚举中间点,比后枚举中间点要慢200.300ms左右,不知道为什么,希望有大佬能帮我解答一下。

    代码如下:

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int N = 16 , M = 1e4+5;
    int a[N][M];
    int dp[N][N][1<<N];
    int n,m;
    int dis[N][N],dis_next[N][N];
    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]);
        memset(dis,INF,sizeof(dis));
        memset(dis_next,INF,sizeof(dis_next));
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j) continue ;
                for(int k=0;k<m;k++) dis[i][j]=min(dis[i][j],abs(a[i][k]-a[j][k]));
                for(int k=0;k<m-1;k++) dis_next[i][j]=min(dis_next[i][j],abs(a[i][k+1]-a[j][k]));
            }
        }
        int ans = 0;
        if(n==1){
            ans = INF;
            for(int i=0;i<m-1;i++) ans=min(ans,abs(a[0][i]-a[0][i+1]));
            printf("%d",ans);
            return 0;
        }
        for(int l=0;l<n;l++) dp[l][l][1<<l]=INF;
        for(int l=1;l<(1<<n);l++){
            for(int i=0;i<n;i++){
                if((l>>i)&1==0) continue ;
                for(int j=0;j<n;j++){
                    if((l>>j)&1 || i==j) continue ;
                    for(int k=0;k<n;k++){
                        if((l>>j)&1==0) continue ;
                        int now = l|(1<<j);
                        dp[i][j][now]=max(dp[i][j][now],min(dp[i][k][l],dis[k][j]));
                    }
                }
            }
        }
        int now = (1<<n)-1;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j) continue ;
                ans=max(ans,min(dp[i][j][now],dis_next[i][j]));
            }
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    65 进程互斥锁的优化实现
    Linux多线程编程
    互斥锁和自旋锁
    64 进程互斥锁的初步实现(下)
    63 进程互斥锁的初步实现(中)
    Linux中断子系统
    62 进程互斥锁的初步实现(上)
    61 进程互斥锁的详细设计
    Linux进程调度的时机
    嵌入式领域linux作为实时操作系统的缺点(转)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10252277.html
Copyright © 2011-2022 走看看