• P3694 邦邦的大合唱站队/签到题(状压dp)


    P3694 邦邦的大合唱站队/签到题

    题目背景

    BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题。

    题目描述

    N个偶像排成一列,他们来自M个不同的乐队。每个团队至少有一个偶像。

    现在要求重新安排队列,使来自同一乐队的偶像连续的站在一起。重新安排的办法是,让若干偶像出列(剩下的偶像不动),然后让出列的偶像一个个归队到原来的空位,归队的位置任意。

    请问最少让多少偶像出列?

    输入输出格式

    输入格式:

    第一行2个整数N,M。

    接下来N个行,每行一个整数a_i(1le a_i le M)ai​​(1ai​​M),表示队列中第i个偶像的团队编号。

    输出格式:

    一个整数,表示答案

    输入输出样例

    输入样例#1:
    12 4
    1
    3
    2
    4
    2
    1
    2
    3
    1
    1
    3
    4
    输出样例#1:
    7

    说明

    【样例解释】

    1  3   √
    3  3
    2  3   √
    4  4
    2  4   √
    1  2   √
    2  2
    3  2   √
    1  1
    1  1
    3  1   √
    4  1   √

    【数据规模】

    对于20%的数据,Nle 20, M=2N20,M=2

    对于40%的数据,Nle 100, Mle 4N100,M4

    对于70%的数据,Nle 2000, Mle 10N2000,M10

    /*
    状压dp
    状态:dp[i]表示i状态下最小的出列(不一致)的个数。
    比如dp[1101]表示从头到位为1/3/4乐队的偶像的最小出列个数。
    
    预处理sum[i][j]表示前i个人中j种的数量
    dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+(r-l-(sum[r][j]-sum[l][j])));
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    
    #define inf 100000000
    #define N 100007
    
    using namespace std;
    int n,m;
    int a[N],dp[(1<<21)+1],sum[N][21];
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            a[i]--;
            for(int j=0; j<m; j++)
            {
                sum[i][j]=sum[i-1][j];
                if(j==a[i]) sum[i][j]++;
            }
        }
        for(int i=0; i<(1<<m); i++) dp[i]=inf;
        dp[0]=0;
        for(int i=0; i<(1<<m); i++)
        {
            int Sum=0;
            for(int j=0; j<m; j++)
                if((1<<j)&i) Sum+=sum[n][j];
            for(int j=0; j<m; j++)
            {
                if((1<<j)&i) continue;
                int num=sum[n][j];
                int r=Sum+num;
                int l=Sum;
                dp[i|(1<<j)]=min(dp[i|(1<<j)],dp[i]+(r-l-(sum[r][j]-sum[l][j])));
            }
        }
        printf("%d
    ",dp[(1<<m)-1]);
        return 0;
    }

    对于全部数据,1le Nle 10^5, Mle 201N105​​,M20

    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    超多sql分步骤类型题解
    sql 高级函数
    sql 每天下单的老客数量
    sql
    面试-JAVA常见回答
    查询员工的累计薪水
    背包问题模板
    动态规划理解合集
    SQL语句统计每天、每月、每年的 数据
    机考刷机-树相关
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7587716.html
Copyright © 2020-2023  润新知