• LOJ#3302. 「联合省选 2020 A | B」信号传递 状压DP+卡常


    对于 $x,y$ 如果 $x$ 在 $y$ 的左面那么 $x ightarrow y$ 的贡献是 $pos[y]-pos[x]$  

    $y ightarrow x$ 的贡献是 $pos[x] imes k+pos[y] imes k.$  

    令 $f[S]$ 表示集合 $S$ 在序列开头,且考虑所有贡献的情况下的最小值.   

    那么转移 $f[S]$ 是十分简单的,但是我们需要用到一个 $trans[x][S]$ 数组,这个数组空间开不下.   

    可以考虑枚举 $i$ 与 $(i-1)$ 的差别,然后相同位不改,只改不同位,理论上只需要修改 $2^m$ 次.   

    那么这部分复杂度就是 $O(m 2^m)$ 的,总复杂度也是 $O(m 2^m)$ 的.  

    code:  

    #include <ctime> 
    #include <cstdio>   
    #include <cstring> 
    #include <algorithm>    
    #define N 100008 
    #define ll long long 
    #define lowbit(x) ((x)&(-(x))) 
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;      
    int n,m,k,T;       
    int f[1<<23];   
    int a[N],lg[1<<23],bi[24]; 
    int h[24],g[24],m1[24][24],m2[24][24],cnt[1<<23];    
    inline void calh(int i) { 
        int pre,x;    
        pre=i-1-(i&(i-1));          
        while(pre) {   
            x=lg[lowbit(pre)]; 
            for(int j=1;j<=m;++j) { 
                h[j]-=m1[j][x];   
            }  
            pre-=lowbit(pre); 
        }   
        pre=i-(i&(i-1)); 
        while(pre) {   
            x=lg[lowbit(pre)]; 
            for(int j=1;j<=m;++j) { 
                h[j]+=m1[j][x];   
            }  
            pre-=lowbit(pre); 
        }   
    }
    inline void calg(int i) { 
        int pre,x;     
        pre=(i+1)-(i&(i+1));                           
        while(pre) {  
            x=lg[lowbit(pre)];         
            for(int j=1;j<=m;++j) { 
                h[j]-=m2[j][x];      
            }  
            pre-=lowbit(pre); 
        }   
        pre=i-(i&(i+1)); 
        while(pre) {      
            x=lg[lowbit(pre)]; 
            for(int j=1;j<=m;++j) { 
                h[j]+=m2[j][x];   
            }  
            pre-=lowbit(pre); 
        }   
    }
    int main() { 
        // setIO("input");    
        scanf("%d%d%d",&n,&m,&k);   
        for(int i=1;i<=n;++i) { 
            scanf("%d",&a[i]); 
        }   
        for(int i=1;i<n;++i) {  
            if(a[i]==a[i+1]) { 
                continue;  
            }
            m1[a[i]][a[i+1]]+=k;
            m1[a[i+1]][a[i]]+=1;                 
            --m2[a[i]][a[i+1]]; 
            m2[a[i+1]][a[i]]+=k;  
        }   
        for(int i=1;i<=m;++i) { 
            bi[i]=1<<(i-1);    
            lg[bi[i]]=i;     
        }                        
        memset(f,0x3f,sizeof(f)); 
        f[0]=0;     
        T=(1<<m)-1;   
        for(int i=1;i<=m;++i) {  
            for(int j=1;j<=m;++j) { 
                h[i]+=m2[i][j];  
            }
        }  
        int x,y,z; 
        for(int i=1;i<(1<<m);++i) {  
            calh(i);  
            calg(T-i);     
            cnt[i]=cnt[i-lowbit(i)]+1;  
            int cur=i;  
            while(cur) { 
                x=lg[lowbit(cur)];  
                f[i]=min(f[i],f[i-bi[x]]+cnt[i]*h[x]); 
                cur-=lowbit(cur); 
            }     
        }  
        printf("%d
    ",(ll)f[T]);  
        return 0; 
    }
    

      

  • 相关阅读:
    Linux查看日志常用命令
    linux(centos)下安装PHP的PDO扩展
    TP thinkphp 权限管理 权限认证 功能
    mysql优化(三)–explain分析sql语句执行效率
    阿里云服务器Centos7成为挖矿肉鸡被挖矿imWBR1耗尽CPU
    Asp.net导入Excel并读取数据
    定义显式类型转换和隐式类型转换
    C# 对象与引用变量
    C# ref参数
    C# 字段与属性的区别
  • 原文地址:https://www.cnblogs.com/guangheli/p/13367329.html
Copyright © 2020-2023  润新知