状压DP 【洛谷P3694】 邦邦的大合唱站队
【洛谷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保证之前的状态站法是最优的)。
转移就比较好想了。
\]
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】 邦邦的大合唱站队的更多相关文章
- 状压搜索 洛谷T47092 作业
		TYM 有 nn 本作业,编号为 1,\dots,n1,…,n. 由于 \mathrm{TYM}TYM 很喜欢偷懒,而且不喜欢消耗脑细胞,所以他选择跳着完成这 nn 本作业.此外,如果将做作业的顺序转 ... 
- [状压DP]P1441 题解 砝码称重
		前置知识:状压DP 洛谷传送门 emm....看到题目,我第一个想到的就是枚举.暴力大法好! 具体怎么枚举?当然是子集枚举啦!枚举出每一个可能的砝码选择方案.对于每一个合法的(也就是选取数量等于\(n ... 
- 洛谷P3694  邦邦的大合唱站队【状压dp】
		状压dp 应用思想,找准状态,多考虑状态和\(f\)答案数组的维数(这个题主要就是找出来状态如何转移) 题目背景 \(BanG Dream!\)里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. ... 
- P3694 邦邦的大合唱站队/签到题(状压dp)
		P3694 邦邦的大合唱站队/签到题 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶 ... 
- P3694 邦邦的大合唱站队  (状压DP)
		题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶像. 现在要求重新安排队列,使来自同一 ... 
- Luogu P3694 邦邦的大合唱站队 【状压dp】By cellur925
		题目传送门 最开始学状压的时候...学长就讲的是这个题.当时对于刚好像明白互不侵犯和炮兵阵地的我来说好像在听天书.......因为我当时心里想,这又不是什么棋盘,咋状压啊?!后来发现这样的状压多了去了 ... 
- 洛谷P3694 邦邦的大合唱站队/签到题
		P3694 邦邦的大合唱站队/签到题 题目背景 BanG Dream!里的所有偶像乐队要一起大合唱,不过在排队上出了一些问题. 题目描述 N个偶像排成一列,他们来自M个不同的乐队.每个团队至少有一个偶 ... 
- 洛谷P3959 宝藏(NOIP2017)(状压DP,子集DP)
		洛谷题目传送门 Dalao的题解多数是什么模拟退火.DFS剪枝.\(O(3^nn^2)\)的状压DP之类.蒟蒻尝试着把状压改进了一下使复杂度降到\(O(3^nn)\). 考虑到每条边的贡献跟它所在的层 ... 
- 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)
		洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ... 
随机推荐
- samba Nginx
			1.samba 2.nfs 3.crond 4.nginx ifconfig yum install net-tools -y ifconfig #查看所有已激活的网卡信息 ifconfig eth0 ... 
- c# 代码调用ssis包
			https://docs.microsoft.com/en-us/sql/integration-services/run-manage-packages-programmatically/loadi ... 
- Latex 多个参考文献的引用
			如果在文章中出现连续引用多个参考文献的情况,希望显示的格式为 [1-5,9,12],那么可以如下处理: 在文章的导言区加 \usepackage[square, comma, sort&com ... 
- import time
			时间相关的操作,时间有三种表示方式: 时间戳 1970年1月1日之后的秒,即:time.time() 格式化的字符串 2014-11-11 11:11, 即:t ... 
- Contentprovider的创建和使用流程概述
			首先在provider类中继承并实现provider的几个必要方法 -- boolean onCreate(),用来执行一些初始化的工作. -- cursor query(Uri, String[], ... 
- java中的面向对象的三大基本特征
			转载,原文来自http://blog.sina.com.cn/s/blog_5f79a56a0100c6ig.html 众所周知,java中的面向对象的三大基本特征是:[封装].[继承].[多态] 一 ... 
- Struts2框架06 ValueStack
			原文地址:点击前往 1 什么是ValueStack 称为值栈,Struts提供的共享数据的数据结构 2 为什么要使用ValueStack 从控制器向浏览器传递数据 存储与请求相关的对象信息(sessi ... 
- SQl Server   Tsql基本编程 ,循环语句  ,存储过程
			一些比较重要但是不一定经常用的 句子 Tsql定义变量 declare @a int : 定义的变量前面必须用@,数据类型是SQL里的数据类型,执行的时候要把需要的有关联的代码一起执行,单独执行一条 ... 
- ROS Learning-003 beginner_Tutorials 创建ROS工作空间
			ROS Indigo beginner_Tutorials-02 创建ROS工作空间 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14.04. ... 
- css选择器的一些说明
			标签选择器.ID选择器.类选择器 这三个很简单,没啥可说的. 子选择器得说一下. <ul class="food"> <li>水果 &l ... 
