洛谷 P3694 邦邦的大合唱站队 状压DP
题目描述

输入输出样例
输入 #1 复制
12 4
1
3
2
4
2
1
2
3
1
1
3
4
输出 #1 复制
7
说明/提示

分析
首先要注意合唱队排好队之后不一定是按\(1.2.3......m\)的顺序的
\(N\)的范围很大,但\(m\)的数据比较小,所以我们考虑装压DP
我们设\(f[i]\)为状态为\(i\)的合唱队已经安排好位置的最小花费
接下来就是状态转移方程的问题
for(int i=1;i<(1<<m);i++){
int len=0;
for(int j=1;j<=m;j++){
if(i&(1<<(j-1))) len+=num[j];
}
for(int j=1;j<=m;j++){
if(i&(1<<(j-1))) f[i]=min(f[i],f[i^(1<<(j-1))]+num[j]-sum[len][j]+sum[len-num[j]][j]);
}
}
第一维枚举的是状态,在枚举状态之后,我们还要统计当前状态下哪些合唱队已经排好了位置
我们用一个变量\(len\)记录排好队的总人数,如果当前合唱队已经排好了队,那么我们把总人数加上当前合唱队的人数
其中,编号为\(j\)的合唱队的总人数\(num[j]\)可以预处理
为什么这样做呢?
因为我们无论让偶像们怎么出队,他们最终的状态是确定的,肯定是一个合唱队的偶像站到一起,因此我们就可以统计排好队后当前区间的总长度
接下来就是状态转移
如果编号为\(j\)的合唱队在我们决策的范围之内,那我们就需要尝试将编号为\(j\)的合唱队的全体成员都放在队伍最后
那么此时我们就需要将编号为\(j\)的合唱队中不在区间\([len-num[j]+1,num[j]]\)的偶像移到该区间
此时的花费为\(num[j]-sum[len][j]+sum[len-num[j]][j]\)
其中\(sum[i][j]\)表示开始时前\(i\)个位置中编号为\(j\)的合唱队员的个数
问题就可以解决了
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=22,maxm=1e5+5;
int f[1<<maxn];
int num[maxn],sum[maxm][maxn];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int aa;
scanf("%d",&aa);
num[aa]++;
for(int j=1;j<=m;j++) sum[i][j]=sum[i-1][j];
sum[i][aa]++;
}
memset(f,0x3f,sizeof(f));
f[0]=0;
for(int i=1;i<(1<<m);i++){
int len=0;
for(int j=1;j<=m;j++){
if(i&(1<<(j-1))) len+=num[j];
}
for(int j=1;j<=m;j++){
if(i&(1<<(j-1))) f[i]=min(f[i],f[i^(1<<(j-1))]+num[j]-sum[len][j]+sum[len-num[j]][j]);
}
}
printf("%d\n",f[(1<< m)-1]);
return 0;
}
洛谷 P3694 邦邦的大合唱站队 状压DP的更多相关文章
- P3694 邦邦的大合唱站队 (状压DP)
题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ...
- 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)
洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...
- 洛谷P1896 [SCOI2005]互不侵犯King【状压DP】
题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 输入格式: 只有一行,包含两个数N,K ...
- 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)
题目链接 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 这是道状压\(DP\)好题啊.. ...
- BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】
[题解] 思维题,看了别人的博客才会写. 写出这样的矩阵: 1,3,9,... 2,6,18,... 4,12.36,... 8,24,72,... 我们要做的就是从矩阵中选出一些数字,但是不能选相邻 ...
- 【洛谷5492】[PKUWC2018] 随机算法(状压DP)
点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...
- 洛谷P2396 yyy loves Maths VII【状压dp】
题目:https://www.luogu.org/problemnew/show/P2396 题意:有n个数,每次选择一个表示走$a[i]$步,每个数只能选一次. 最多有两个厄运数字,如果走到了厄运数 ...
- 洛谷 3112 [USACO14DEC]后卫马克Guard Mark——状压dp
题目:https://www.luogu.org/problemnew/show/P3112 状压dp.发现只需要记录当前状态的牛中剩余承重最小的值. #include<iostream> ...
- 洛谷 P7324 - [WC2021] 表达式求值(状压+dp)
题面传送门 现场人傻系列-- 首先建出 \(E\) 的表达式树,具体来说表达式的每一个叶子节点表示一个数组 \(A_i\),每一个非叶子节点都表示一次运算,它的值表示左右儿子进行该运算后得到的结果.这 ...
随机推荐
- centos 7 源码安装openssh
环境:centos 7.1.1503 最小化安装 依赖包下载: yum -y install lrzsz zlib-devel perl gcc pam-devel 1.安装openssl ,选用最 ...
- Javascript 随机显示数组元素
$(function(){ var wx_arr = ['gb3055','gb6365']; var storage = window.localStorage; function random_w ...
- Linux中tomcat的部署
红帽7如何配置tomcat 1.下载tomcat9.0和java-1.8 tomcat的下载地址: https://tomcat.apache.org/ java1.8是radhat7自带: [roo ...
- VS Code项目中共享自定义的代码片段方案
VS Code项目中共享自定义的代码片段方案 一.问题背景 项目中注释风格不统一,如何统一注释风格 一些第三方组件库名称太长,每次使用都需要找文档,然后复制粘贴 部分组件库有自己的Snippets插件 ...
- Jenkins登录无效
解决办法: 进入Jenkins安装目录: 1:进入D:\jenkins\users\admin 这个目录下找到config.xml 可以看到里面的用户名是admin 2:进入D:\jenkins\s ...
- Android学习笔记物理按键事件处理
常见的物理按键: Android为每个物理按键都提供了如下几个回调方法: 代码示例: package com.example.demo3; import androidx.appcompat.app. ...
- 《Java并发编程的艺术》第6/7/8章 Java并发容器与框架/13个原子操作/并发工具类
第6章 Java并发容器和框架 6.1 ConcurrentHashMap(线程安全的HashMap.锁分段技术) 6.1.1 为什么要使用ConcurrentHashMap 在并发编程中使用Has ...
- 查看apk安装包信息
➜ sdk aapt dump badging ~/Downloads/PermRoot8006.apk package: name='com.qihoo.permmgr' versionCode=' ...
- cc22a_demo_c++重载自增自减操作符-代码示范
cc22a_demo_c++重载自增自减操作符-代码示范 #define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespa ...
- Mysql表结构转成Oracle
Navicat数据库连接工具