- Author: zifeiy
- Tags: shaped pressure DP, DP subsetting
Link Title: https://codeforces.com/contest/1238/problem/E
Title effect:
to give you a length \ (n (n \ le 10 ^ 5) \) of the string s and \ (m (m \ 20 is Le) \) , the string of prior \ (m \) lowercase letters.
Now you find a front \ (m \) a permutation p characters, generating a string s based on the arrangement of the p, and calculate the total costs.
Calculation cost is:
For example, I have now generated before the i-th character of the string s \ (1..i S_ {} \) , and now I want to generate a first character i + 1 \ (s_ {i + 1} \) , and I assume \ (S_I \) corresponding character is x, \ (S_ {I +. 1} \) corresponding character is y, and the character x in the arrangement of p in position \ (pos_x \) , character y position in the array is p \ (pos_y \) , then the generated character \ (s_ {i + 1} \) after an increase of the total cost of \ (| pos_x - pos_y | \) .
You need to find the minimum total cost of all permutations of the total cost of the minimum program of the corresponding program.
Topic analysis:
First, we can look at the official explanations :
Explain to the official website of which involved a "subset dynamic programming", I would roughly translate it as "a subset of dynamic programming", in fact, the purpose of this question can be found in the sub-1 really set with some exercises.
At the same time it is compressed with the state also has some relationship.
We use i to represent each state ( \ (0 \ Le i \ lt 2 ^ m \) ), the i in fact corresponds to a binary number is a binary m-bit, if the j-th bit i is 1 it means the state has put a j-th character, otherwise there is no explanation to put the j-th character, then we can put the j-th character, that is to say:
by state i
and character j
can be extended out of a new state i | (1<<j)
.
And j
put in the position it is determined - we can use the function __builtin_popcount(i)
to get the binary representation of i species exist how many bits to 1.
Then here I think the most important point is bothering me for a long time is a point - "How to eliminate the impact position" .
In fact, for each state i
and character j
, from the state if you want to i
transfer to the state i | (1<<j)
, and we assume that i
the binary representation has c bit is 1, then we can actually find the location in which the arrangement of j is determined, it is c (also can be c + 1, depending on your initial coordinate this decision, we here assumed to be the c).
But so far we can not eliminate the influence of distance.
We can enumerate i k-bit status inside:
- If state i k-bit is 1, then that it has been placed before the character k state i to a place (we assume \ (c_k \) ),
so now we have to put the j in the c-th position ( for clarity, we let \ (c_j \) represents c),
then k and j price should be \ (cnt [j] [k] \ Times (C_J - c_k) \) ; (because \ (c_k \ lt c_j \) ) - If state i k-bit is 0, then that is not a state i k character to a place (we assume \ (c_k \) ),
so now we have to put the j in the c-th position (for clarity we make \ (c_j \) represents c),
then j and k cost should be \ (cnt [j] [k] \ Times (c_k - C_J) \) . (Since \ (C_J \ C_K lt \) )
So, we can see that if I had let \ (f [i] \) denote i the state minimum total consideration,
then, when our current judgment state i and character j (and we assume that the j-bit i is 0 , because at this time we can state i
plus the characters j
change to a new state i | (1<<j)
).
We started to open a variable \ (tmp = F [I] \) , and from 0 to m-1 traversing a character to k:
- If k is already present in the state i, then \ (tmp - CNT = [k] [J] \ C Times \) ;
- If k does not already exist in the state i, then \ (tmp + = CNT [k] [J] \ Times C \) . (Where c is the previous position of said character j into state i)
Why then such a position eliminates the effects?
We assume now time to put j has not put k, then our tmp variable subtracted \ (cnt [k] [j] \ Times C_J \) , then after going to put k, we will add the variable tmp on \ (cnt [k] [J] \ Times c_k \) , and \ (c_k - c_j \) is actually their distance, so one plus one minus to indirectly deal with the distance (this point puzzled me for a long time until suddenly see the light!).
Then, for each state i and j characters (j-th bit in claim state i is 0), and tmp calculated:
f[ i | (1<<j) ] = max(f[ i | (1<<j) ] , tmp);
Codes are as follows:
#include <bits/stdc++.h>
using namespace std;
int n, m, f[(1<<20)], cnt[20][20];
string s;
int main() {
cin >> n >> m >> s;
for (int i = 1; i < n; i ++) {
int a = s[i-1] - 'a', b = s[i] - 'a';
if (a != b) {
cnt[a][b] ++;
cnt[b][a] ++;
}
}
fill(f+1, f+(1<<m), INT_MAX);
for (int i = 0; i < (1<<m)-1; i ++) {
int c = __builtin_popcount(i);
for (int j = 0; j < m; j ++) {
if ( !( i & (1<<j) ) ) {
int tmp = f[i];
for (int k = 0; k < m; k ++) {
if (i & (1<<k)) {
tmp += cnt[j][k] * c;
}
else { // 因为预处理cnt的时候保证cnt[x][x]==0
tmp -= cnt[j][k] * c;
}
}
f[ i | (1<<j) ] = min(f[i | (1<<j)], tmp);
}
}
}
cout << f[ (1<<m)-1 ] << endl;
return 0;
}