zoukankan      html  css  js  c++  java
  • codeforces#1215E. Marbles(状压DP)

    题目大意:给出一个由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];
    }
    
  • 相关阅读:
    Java+7入门经典 -1 简介
    优化算法动画演示Alec Radford's animations for optimization algorithms
    如何写科技论文How to write a technical paper
    开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
    用500行Julia代码开始深度学习之旅 Beginning deep learning with 500 lines of Julia
    用10张图来看机器学习Machine learning in 10 pictures
    ICLR 2013 International Conference on Learning Representations深度学习论文papers
    ICLR 2014 International Conference on Learning Representations深度学习论文papers
    卷积神经网络CNN(Convolutional Neural Networks)没有原理只有实现
    卷积神经网络Convolutional Neural Networks
  • 原文地址:https://www.cnblogs.com/MisakaMKT/p/11597366.html
Copyright © 2011-2022 走看看