zoukankan      html  css  js  c++  java
  • P3694 邦邦的大合唱站队

    题面

    看范围,N 较大, M 符合状压的范围。

    f[S] 表示 编号为L(L是S的一位的团队)且这一位为1 的团队已经摆好了.例如1011就是将1,2,4团队的歌手都摆好的最小值。

    我们考虑如何转移。在Dp转移中,我们都是通过决策,将未知的状态由已知的状态推出,那么决策显然就是将一个团队的歌手摆好需要多摆几个人

    假设现在状态集合为S,那么少一个歌手团队的集合就是S ^ (1 << j-1) ,这个集合我们设为K,那么f[S] 就由 f[K]转移。

    我们就让K集合比S集合少的人数累计到答案里。特别显然的是,肯定不需要所有人都离开位置,以前就在那个位置上的可以不移动,所以在减去原先就在那个范围的人。

    我们需要预处理很多东西

    1.我们需要预处理sum[i]表示i团队一共有多少人,预处理简单

    2.我们需要预处理1 - j的这些位置i团队有多少人,q[i][j]

    3.我们需要预处理集合S中,某些位是1的歌手的和

    完整的方程就是

    f[S] = f[K] + sum[j] -(q[j][s[i]] - q[j][s[K]]);

    K = S ^ (1 << j-1)

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    const int M = 22;
    int f[1 << M];
    int n, m;
    int a[N], q[M][N];
    //前缀和,q[M][N];q[i][j] 1 - j 有多少个i团队的人
    //The number of singers who work in the team i that singing in (1 to j) 
    int sum[M];
    int S[1 << M];
    
    int main(){
        cin >> n >> m;
        for(int i = 1;i <= n;++ i)
        cin >> a[i];
        for(int i = 1;i <= n;++ i){
            sum[a[i]] ++;
            q[a[i]][i] = 1;
        }
        for(int i = 1;i <= n;++ i){
            for(int j = 1;j <= m;++ j)
            q[j][i] += q[j][i-1];
        }
        for(int i = 1;i < 1 << m;++ i){//O(2^m * m)
            int k = 0;
            int tmp = i;
            while(tmp){
                ++ k;
                if(tmp & 1) S[i] += sum[k];
                tmp >>= 1;
            }
        }
        memset(f, 0x3f, sizeof  f);
        f[0] = 0;
        for(int i = 1;i < 1 << m;++ i){
            for(int j = 1;j <= m;++ j){
                int k = i ^ (1 << (j - 1));
                f[i] = min(f[i], f[k] + sum[j] - (q[j][S[i]] - q[j][S[k]]));
            }
        }
        cout << f[(1<<m)-1];
        
        return 0;
    }
  • 相关阅读:
    HTML_<select>
    HTML_<a>
    MySQL_知识点
    MySQL_常用SQL语句
    GIT
    MyBatis_传入参数的问题
    js函数防抖与节流总结
    node 常用方法 生成密钥 token验证 验证码生成 (持续更新)
    node 登陆拦截中间件(egg)
    js 给页面容器增加水印
  • 原文地址:https://www.cnblogs.com/Shu-Kuang/p/13325037.html
Copyright © 2011-2022 走看看