CF1238 E. Compra do teclado 【Divisão de pressão de estado / subconjunto DP】

Link do título: CF1238 E.Keyboard Purchase

Pergunta: Dê a você uma string de comprimento n (1e5) composta das primeiras m letras e peça para determinar um arranjo das primeiras m (20) letras. O valor de cada letra é sua posição no arranjo. O custo de a string original é a diferença de valor entre duas letras adjacentes Qual é o custo mínimo da string;

Análise: Em primeiro lugar, o número de ocorrências de combinações de letras adjacentes pode ser pré-processado; considerando a compressão de estado, a i-ésima posição é 1 significa que a posição da i-ésima letra foi determinada e 0 significa que sua posição não é determinado, então em um estado O número x de 1 significa que já existem x números na posição de 0 ~ x-1, então o número da posição indecisa pode ser colocado na posição de x ~ m-1, e então o estado viável é atualizado para trás; o método de atualização Sim, defina a letra processada atualmente como a e enumere outra letra b, então ans + = cnt [a] [b] * abs (pos_a-pos_b), de acordo com o que dissemos antes , se b apareceu, então pos_b <pos_a, Caso contrário pos_a <pos_b; usando a ideia de diferença, se b não apareceu, ans- = cnt [a] [b] * pos_a, caso contrário, ans + = cnt [a ] [b] * pos_a;

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define pb push_back
typedef long long ll;
const int maxn=(int)1e5+100;
const int mod=(int)1e9+7;
int n,m,cnt[21][21],dp[1<<21];
char s[maxn];
int main(){
    scanf("%d%d%s",&n,&m,s+1);
    rep(i,2,n) cnt[s[i-1]-'a'][s[i]-'a']++,cnt[s[i]-'a'][s[i-1]-'a']++;
    rep(i,1,(1<<m)) dp[i]=INT_MAX;
    rep(mk,0,(1<<m)-1-1){
        int num= __builtin_popcount(mk);
        rep(i,0,m-1) if((mk&(1<<i))==0){
            int tmp=dp[mk];
            rep(j,0,m-1){
                if(i==j) continue;
                if(mk&(1<<j)) tmp+=cnt[i][j]*num;
                else tmp-=cnt[i][j]*num;
            }
            dp[mk|(1<<i)]=min(dp[mk|(1<<i)],tmp);
        }
    }
    printf("%d\n",dp[(1<<m)-1]);
}

    

 

Acho que você gosta

Origin blog.csdn.net/qq_43813163/article/details/102556946
Recomendado
Clasificación