CF1238 E.Keyboard Purchase【State Pressure/Subset Division DP】

Title link: CF1238 E.Keyboard Purchase

Question: Give you a string of length n (1e5) composed of the first m letters, and ask you to determine an arrangement of the first m (20) letters. The value of each letter is its position in the arrangement. The cost of the original string is the difference in value between two adjacent letters. What is the minimum cost of the string;

Analysis: Firstly, the number of occurrences of adjacent letter combinations can be preprocessed; considering the state compression, the i-th position is 1 means that the position of the i-th letter has been determined, and 0 means that its position is not determined, then in a state The number x of 1 means that there are already x numbers in the position of 0~x-1, then the number of the undecided position can be placed at the position of x~m-1, and then the feasible state is updated backward; the method of updating Yes, set the currently processed letter as a and enumerate another letter b, then ans+=cnt[a][b]*abs(pos_a-pos_b), according to what we said before, if b has appeared, then pos_b<pos_a , Otherwise pos_a<pos_b; using the idea of ​​difference, if b has not appeared, ans-=cnt[a][b]*pos_a, otherwise, 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]);
}

    

 

Guess you like

Origin blog.csdn.net/qq_43813163/article/details/102556946