题目大意:给出一个由N个整数组成的序列,通过每次交换相邻的两个数,使这个序列的每个相同的数都相邻。求最小的交换次数。

比如给出序列:1 2 3 2 1 ,那么最终序列应该是 1 1 2 2 3 ,最小交换次数为4.

输入格式

第一行输入一个数字n(2≤n≤4*10^5),表示大理石的总数。

第二行输入n个数字a1,a2…,an(1≤ai≤20)表示第i块大理石的颜色为ai。

输出格式

最少交换的次数。

样例

样例输入 1

7

3 4 2 3 4 2 2

样例输出 1

3

样例输入 2

5

20 1 14 10 2

样例输出 2

0

样例输入 3

13

5 5 4 4 3 5 7 6 5 4 4 6 5

样例输出 3

21

可以发现这道题的操作比较复杂,N的数量级也很大,\(N^2\)的时间复杂度肯定是行不通的。

对于这种题,我们可以先通过几组样例来构思出整道题的模型。

所以我们不妨考虑只有两种数的情况,对于数列 \(11221\),它的最终状态其实有两种\(11122\)和\(22111\)。我们统计每个数字2前面与它不同的数字的个数,分别是 2 + 2共需4次,这就是将所有的数字2全部移到左边所需要的次数,同理统计1的话只需2次。

现在我们来考虑多种数字的情况。我们发现这种情况不能直接通过上述方法来得出。但可以得到一个普遍的但不一定是最优的方法:

每次将一种数字全部移到左边,再将第二种数字全部移到左边(这时我们不能考虑第一种数字)。。。依次类推。

但每次移动哪种数字我们却不能确定,于是可以使用状压DP。

因为题目中\(1<=A_{i}<=20\)。设当前状态为S,如果S的第\(i\)位为1,则第\(i\)种颜色已经被选过,统计答案时便不需要统计第\(i\)种。

(大致思路已经给出,具体变量的含义请见注释)

#include <bits/stdc++.h>
using namespace std; #define N 400010
#define M 30
#define LL long long int A[N],n,pre[M][M];
LL f[1<<21];
vector<int> chos[M]; int main() {
cin>>n;
for(LL i=1;i<=n;i++) {
cin>>A[i];
chos[A[i]].push_back(i);//统计每种数字的下标,放入vector储存
}
//预处理
for(LL i=1;i<=20;i++)
for(LL j=1;j<=20;j++) {
if(i==j || chos[i].size()==0 || chos[j].size()==0) continue;
//统计答案
for(LL k=0,v;k<chos[i].size();k++) {
v=chos[i][k];
if(v<chos[j][0]) continue;
pre[i][j]+=lower_bound(chos[j].begin(),chos[j].end(),v)-chos[j].begin();
//二分查找离当前数字最近的指定的下标,这就是需要交换的次数,进行累加
}
}
memset(f,0x3f,sizeof(f));
f[0]=0;
for(LL i=0;i<(1<<20);i++)
for(LL j=1;j<=20;j++) //DP部分
if(!(i&(1<<(j-1)))) {
LL sum=0;
for(LL k=0;k<20;k++)
if(i&(1<<k))
sum+=pre[k+1][j];
f[i|(1<<(j-1))]=min(f[i|(1<<(j-1))],f[i]+sum);
}
cout<<f[(1<<20)-1];
}

codeforces#1215E. Marbles(状压DP)的更多相关文章

  1. E. Marbles 状压dp

    E. Marbles 这个是一个状压dp 题目大意是:给你一个数组,数组的数在1到20之间,有一个操作就是交换相邻的两个数,问 让所有相同的数相邻的最小操作次数 dp[s] 表示s状态下的操作次数,w ...

  2. codeforces 11D(状压dp)

    传送门:https://codeforces.com/problemset/problem/11/D 题意: 求n个点m条边的图里面环的个数 题解: 点的范围只有19,很容易想到是状压. dp[sta ...

  3. Codeforces Round #585 (Div. 2) E. Marbles(状压dp)

    题意:给你一个长度为n的序列 问你需要多少次两两交换 可以让相同的数字在一个区间段 思路:我们可以预处理一个数组cnt[i][j]表示把i放到j前面需要交换多少次 然后二进制枚举后 每次选择一个为1的 ...

  4. Codeforces 1215E 状压DP

    题意:给你一个序列,你可以交换序列中的相邻的两个元素,问最少需要交换多少次可以让这个序列变成若干个极大的颜色相同的子段. 思路:由于题目中的颜色种类很少,考虑状压DP.设dp[mask]为把mask为 ...

  5. Codeforces Round #585 (Div. 2) E. Marbles (状压DP),BZOJ大理石(同一道题)题解

    题意 林老师是一位大理石收藏家,他在家里收藏了n块各种颜色的大理石,第i块大理石的颜色为ai.但是林老师觉得这些石头在家里随意摆放太过凌乱,他希望把所有颜色相同的石头放在一起.换句话说,林老师需要对现 ...

  6. codeforces Diagrams & Tableaux1 (状压DP)

    http://codeforces.com/gym/100405 D题 题在pdf里 codeforces.com/gym/100405/attachments/download/2331/20132 ...

  7. Codeforces Gym 100015F Fighting for Triangles 状压DP

    Fighting for Triangles 题目连接: http://codeforces.com/gym/100015/attachments Description Andy and Ralph ...

  8. Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP

    Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...

  9. 状压dp Codeforces Beta Round #8 C

    http://codeforces.com/contest/8/problem/C 题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的 ...

随机推荐

  1. 关于CSS你应该知道的基础知识 - 盒模型篇

    浏览器渲染引擎通过盒模型的方式来布局html元素.我们可以将每一个html元素都看做是一个盒子,每一个盒子都有长和款,多个这样的盒子组成了我们的网页. Margin,Border,Padding 每一 ...

  2. 基于python3环境下搭建Robot Framework 自动化测试框架(一)

    大家都知道,Robot Framework 是基于python2 环境 的一套自动化测试工具,据说python 2 到2020年不维护,现在用python 3 的环境搭建Robot Framework ...

  3. SpringCloud创建Eureka

    Eureka是什么 Eureka是Netflix的一 个子模块,也是核心模块之一- .Eureka是一 个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移.服务注册与发现对于微服务 ...

  4. 【BZOJ3601】一个人的数论

    题目链接 题意简述 求小于 n 且与 n 互质的数的 k 次方之和. Sol 要求的东西: \[\sum_{i=1}^n i^k [gcd(i,n)=1]\] 枚举 gcd 上个莫比乌斯函数: \[\ ...

  5. Python---进阶---文件操作---比较文件不同

    一.编写一个程序,接受用户输入的内容,并且保存为新的文件 如果用户单独输入:w 表示文件保存退出 --------------------------------------------- file_ ...

  6. SpringCloud学习系列-微服务

    最近和尚硅谷周阳老师学习了Spring Cloud感觉有必要在这里做下笔记和总结. 软件系统架构演变 单一应用架构当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本.此时,用 ...

  7. 【leetcode】1108. Defanging an IP Address

    题目如下: Given a valid (IPv4) IP address, return a defanged version of that IP address. A defanged IP a ...

  8. watch和computed

    watch和computed都是以Vue的依赖追踪机制为基础的,它们都试图处理这样一件事情:当某一个数据(称它为依赖数据)发生变化的时候,所有依赖这个数据的“相关”数据“自动”发生变化,也就是自动调用 ...

  9. js 遍历数组取出字符串用逗号拼接

    var arr = [{"name":"hhh"},{"name":"dddd"}] //用js function ge ...

  10. BZOJ 3329: Xorequ(数位dp+递推)

    传送门 解题思路 可以把原式移项得\(x\)^\(2x\)=\(3x\),而\(x+2x=3x\),说明\(x\)二进制下不能有两个连续的\(1\).那么第一问就是一个简单的数位\(dp\),第二问考 ...