CodeForces EduRound 74


E: Keyboard Purchase

题意

给你一个有小写字母组成的字符串,让你给每个字母编号,使得$\sum\limits_{i=1}^{n}|S_i-S_{i-1}|$的值最小

思路

因为字母种类很小,所以我们可以用类似状压来记录中间值,具体的是$dp[(1<<m)]$来记录当前状态出现的字母种类与还未出现的字母种类的距离。

我们现在先想象一个键盘,$dp[i]$的二进制表示就是键盘前几个的键,那么$dp[i]$的转移就是由$dp[i^(1<<j)]$新加了一位j转移得来:

for (int i = 1; i < (1<<m); i ++) {
        dp[i] = 0x3f3f3f3f;
        for (int j = 0; (1<<j) <= i; j ++) 
            if((i>>j)&1) dp[i] = min(dp[i], dp[i^(1<<j)]);
    }

得到的就是当前状态下的最小花费,

那么这样的话,原来的$dp[i^(1<<j)]$的状态不确定的这一位已经确定,那么其他还尚未却动的键与当前已经确定的键之间的距离要$+1$,

for (int i = 1; i < (1<<m); i ++) {
        dp[i] = 0x3f3f3f3f;
        for (int j = 0; (1<<j) <= i; j ++) 
            if((i>>j)&1) dp[i] = min(dp[i], dp[i^(1<<j)]);
        for (int j = 0; (1<<j) <= i; j ++) 
            if((i>>j)&1) 
                for (int k = 0; k < m; k ++) 
                    if(!((i>>k)&1)) dp[i] += adj[j][k];
    }

AC代码

#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int maxn = 1e5 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef pair<int, int> pis;

int dp[(1<<21)];
int adj[30][30];

int main() { 
    int n, m;
    scanf("%d %d", &n, &m);
    string st;
    cin >> st;
    for (int i = 1; i < st.size(); i ++) {
        adj[st[i]-'a'][st[i-1]-'a'] ++;
        adj[st[i-1]-'a'][st[i]-'a'] ++;
    }
    for (int i = 1; i < (1<<m); i ++) {
        dp[i] = 0x3f3f3f3f;
        for (int j = 0; (1<<j) <= i; j ++) 
            if((i>>j)&1) dp[i] = min(dp[i], dp[i^(1<<j)]);
        for (int j = 0; (1<<j) <= i; j ++) 
            if((i>>j)&1) 
                for (int k = 0; k < m; k ++) 
                    if(!((i>>k)&1)) dp[i] += adj[j][k];
    }
    printf("%d\n", dp[(1<<m)-1]);
    return 0;
}

文章作者: Mug-9
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mug-9 !
评论
  目录