P3694-邦邦的大合唱站队【状压dp】

    科技2024-08-04  23

    正题

    题目链接:https://www.luogu.com.cn/problem/P3694


    题目大意

    n n n个人,有 m m m个队伍,每个人都属于一个队伍。要求叫出一些人来,然后任意插入出来的空隙中使得同一队的人在一起。求最少出列人数。


    解题思路

    如果知道最终的队列就可以十分容易的计算答案了。考虑一个一个队伍的放入最终序列中,因为 m m m十分的小,所以我们可以状压表示排好了的队伍集合,然后用一个前缀和统计在一个区域内每个队伍的人数即可进行 d p dp dp

    时间复杂度 O ( n m + 2 m m ) O(nm+2^mm) O(nm+2mm)


    c o d e code code

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,s[110000][20],wz[1<<20],f[1<<20]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ int x;scanf("%d",&x);x--; for(int j=0;j<m;j++) s[i][j]=s[i-1][j]+(x==j); } int MS=1<<m; for(int i=0;i<MS;i++) for(int j=0;j<m;j++) wz[i]+=s[n][j]*((i>>j)&1); memset(f,0x3f,sizeof(f));f[0]=0; for(int i=1;i<MS;i++){ for(int j=0;j<m;j++){ int k=i^(1<<j); if(k>i)continue; f[i]=min(f[i],f[k]+s[n][j]-s[wz[i]][j]+s[wz[k]][j]); } } printf("%d",f[MS-1]); }
    Processed: 0.010, SQL: 8