zoukankan      html  css  js  c++  java
  • luogu P3694 邦邦的大合唱站队 |状压DP

    题目描述

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

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

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

    输入格式

    第一行2个整数N,M。

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

    输出格式

    一个整数,表示答案


    #include <bits/stdc++.h>
    using namespace std;
    #define int long long
    inline int read(){
    	int res=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}	
    	while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+ch-'0';ch=getchar();}
    	return res*f;
    }
    const int N=1e5+5,M=(1<<21);
    int n,m;
    int dp[M],sum[N][21];
    signed main(){
    	n=read(),m=read();
    	for(int i=1,x;i<=n;i++){
    		x=read();
    		for(int j=1;j<=m;j++)sum[i][j]=sum[i-1][j];
    		sum[i][x]++;
    	}
    	memset(dp,0x3f,sizeof(dp));
    	dp[0]=0;
    	for(int S=0;S<(1<<m);S++){
    		int finish=0;
    		for(int j=0;j<m;j++)if((S>>j)&1)finish+=sum[n][j+1];
    		for(int j=0;j<m;j++){
    			if((S>>j)&1)continue;
    			int l=finish,r=l+sum[n][j+1];
    			dp[S|(1<<j)]=min(dp[S|(1<<j)],dp[S]+sum[n][j+1]-(sum[r][j+1]-sum[l][j+1]));
    		}
    	}
    	cout<<dp[(1<<m)-1]<<endl;
    }
    
  • 相关阅读:
    系统调用简单总结
    系统调用原理详解
    总结:c 语言与Linux操作系统的关系
    poj3171 Cleaning Shifts
    洛谷P1032 字串变换
    poj3662 Telephone Lines
    洛谷P1073 最优贸易
    Uva1330/poj1964 City Game
    poj2559/SP1805 Largest Rectangle in a Histogram
    洛谷 P1196 [NOI2002]银河英雄传说
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/13155652.html
Copyright © 2011-2022 走看看