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

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

$y \rightarrow x$ 的贡献是 $pos[x] \times k+pos[y] \times 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\n",(ll)f[T]);  
    return 0; 
}

  

posted @ 2020-07-23 17:00  EM-LGH  阅读(159)  评论(0编辑  收藏  举报