【洛谷P3694】 邦邦的大合唱站队

题目背景

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

题目描述

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

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

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

输入输出格式

输入格式:

第一行2个整数N,M。

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

输出格式:

一个整数,表示答案

一开始看这个题真的没有思路,想了一下直接写了个爆搜,枚举每个团队的开头位置在求答案取最小。

真的意外可以过70分。

暴搜

code:

#include<iostream>
#include<cstdio>
using namespace std;
const int wx=201007;
int tot[wx],sum[wx][17],vis[wx],pre[wx],last[wx],E[wx];
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int n,m,x;
int ans=0x3f3f3f3f;
void dfs(int now,int end,int num){
if(now==m+1&&end==n){
ans=min(ans,num);
return ;
}
if(num>=ans)return;
for(int i=1;i<=m;i++){
if(vis[i])continue;
vis[i]=1;
dfs(now+1,end+tot[i],tot[i]-sum[end+tot[i]][i]+sum[end][i]+num);
vis[i]=0;
}
}
signed main(){
n=read();m=read();
for(int i=1;i<=n;i++){
x=read();
for(int j=1;j<=m;j++)sum[i][j]=sum[i-1][j];
sum[i][x]=sum[i-1][x]+1;
tot[x]++;
}
dfs(1,0,0);
printf("%d\n",ans);
return 0;
}

正解知道是状压,但是连状态都不会设(菜死了菜死了。。。)

看了大佬博客才发现这题设了状态就完事了。。。

设\(f(i)\)表示当前状态下的最优答案。因为数据范围,肯定是要状压m,怎么压是个问题。

其实我们用二进制的一位表示一个团队,那么1代表这个团队已经站好了,0表示还没有站好。

这里的站好定义要明确,就是这个团队里的每个人都紧挨着了,并且我们默认这些团队都是从头开始向后紧挨着的,(每一次取min保证之前的状态站法是最优的)。

转移就比较好想了。

\[f(i)=f(i\ ^ \ (1<<j-1))+tot(j)-(sum(pos+tot(j))(j)-sum(pos)(j))
\]

pos就是当前不算第i个团队的人的最后位置,枚举一边就可以了。

复杂度\(O(m*2^m)\)

DP

code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int wx=100017;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int n,m;
int f[1<<20],sum[wx][21],tot[21];
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
int x;
x=read();
for(int j=1;j<=m;j++)sum[i][j]=sum[i-1][j];
sum[i][x]=sum[i][x]+1;
tot[x]++;
}
memset(f,0x3f,sizeof f);
f[0]=0;int WX=(1<<m);
for(int i=1;i<WX;i++){
int pos=0;
for(int j=1;j<=m;j++){
if(i&(1<<j-1)){
pos+=tot[j];
}
}
for(int j=1;j<=m;j++){
if(i&(1<<j-1)){
f[i]=min(f[i],f[i^(1<<j-1)]+tot[j]+sum[pos-tot[j]][j]-sum[pos][j]);
}
}
}
printf("%d\n",f[WX-1]);
return 0;
}

状压DP 【洛谷P3694】 邦邦的大合唱站队的更多相关文章

  1. 状压搜索 洛谷T47092 作业

    TYM 有 nn 本作业,编号为 1,\dots,n1,…,n. 由于 \mathrm{TYM}TYM 很喜欢偷懒,而且不喜欢消耗脑细胞,所以他选择跳着完成这 nn 本作业.此外,如果将做作业的顺序转 ...

  2. [状压DP]P1441 题解 砝码称重

    前置知识:状压DP 洛谷传送门 emm....看到题目,我第一个想到的就是枚举.暴力大法好! 具体怎么枚举?当然是子集枚举啦!枚举出每一个可能的砝码选择方案.对于每一个合法的(也就是选取数量等于\(n ...

  3. 洛谷P3694 邦邦的大合唱站队【状压dp】

    状压dp 应用思想,找准状态,多考虑状态和\(f\)答案数组的维数(这个题主要就是找出来状态如何转移) 题目背景 \(BanG Dream!\)里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. ...

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

    P3694 邦邦的大合唱站队/签到题 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶 ...

  5. P3694 邦邦的大合唱站队 (状压DP)

    题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ...

  6. Luogu P3694 邦邦的大合唱站队 【状压dp】By cellur925

    题目传送门 最开始学状压的时候...学长就讲的是这个题.当时对于刚好像明白互不侵犯和炮兵阵地的我来说好像在听天书.......因为我当时心里想,这又不是什么棋盘,咋状压啊?!后来发现这样的状压多了去了 ...

  7. 洛谷P3694 邦邦的大合唱站队/签到题

    P3694 邦邦的大合唱站队/签到题 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶 ...

  8. 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)

    洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ...

  9. 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)

    洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...

随机推荐

  1. SQL命令优化

    与数据库交互的基本语言是sql,数据库每次解析和执行sql语句多需要执行很多步骤.以sql server为例,当数据库收到一条查询语句时,语法分析器会扫描sql语句并将其分成逻辑单元(如关键词.表达式 ...

  2. iOS类目、延展和协议

    类目:为已知的类增加新的方法:注意:类目里面只能写方法,不能写声明和属性,所以,类目不能作为接口来用 1.类目无法向已有类中添加实例变量.2.如果类目中的方法和已有类中的方法名称冲突时,类目中的方法优 ...

  3. C# Math.Round

    不能直接调用Math.Round方法的,这可和Java的不一样哦Math.Round这个函数的解释是将值按指定的小数位数舍入,并不就是四舍五入.这种舍入有时称为就近舍入或四舍六入五成双 C# code ...

  4. Oracle Sql中输入特殊字符 转义字符

    1.单引号,出现在单引号对中的'号必须成对出现,每对代表一个', 例如select '''' from dual; 结果:' 前后两个'代表正常字符串,中间两个''代表一个',此语句输出结果只有一个'

  5. ehcache缓存入门学习

    ehcache缓存入门学习 1,概念 特性 EhCache 是一个纯Java的进程内缓存框架,具有快速.精干等特点,是Hibernate中默认的CacheProvider. 主要的特性有:1. 快速2 ...

  6. 问题:C#打开一个文本文档往里面写数据,没有就新建文档 ;结果:c#FileStream文件读写(转)

    FileStream对象表示在磁盘或网络路径上指向文件的流.这个类提供了在文件中读写字节的方法,但经常使用StreamReader或 StreamWriter执行这些功能.这是因为FileStream ...

  7. does not contain bitcode. You must rebuild it with

    *** does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE ...

  8. ARQ

    自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层和传输层的错误纠正协议之一.它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输.如果 ...

  9. 关于play!的attachments.path配置、以及关于Form表单上传请求的认识

    相关链接 form表单提交multipart/form-data的请求分析:http://blog.csdn.net/five3/article/details/7181521.http://blog ...

  10. C++知识点总结(四)——面向对象的编程细节总结

    1.空类的默认函数 一般情况下,对于任意一个类A,如果程序员不显示的声明和定义上述函数,C++编译器将会自动的为A产生4个public inline(公有.内联)的默认函数,这4个函数最常见的形式为: ...