Codeforces Round #405 Div. 1 Bear and Company(DP)

来源:互联网 发布:mac windows 10 驱动 编辑:程序博客网 时间:2024/05/29 19:11

Bear Limak prepares problems for a programming competition. Of course, it would be unprofessional to mention the sponsor name in the statement. Limak takes it seriously and he is going to change some words. To make it still possible to read, he will try to modify each word as little as possible.

Limak has a string s that consists of uppercase English letters. In one move he can swap two adjacent letters of the string. For example, he can transform a string "ABBC" into "BABC" or "ABCB" in one move.

Limak wants to obtain a string without a substring "VK" (i.e. there should be no letter 'V' immediately followed by letter 'K'). It can be easily proved that it's possible for any initial string s.

What is the minimum possible number of moves Limak can do?

Input

The first line of the input contains an integer n (1 ≤ n ≤ 75) — the length of the string.

The second line contains a string s, consisting of uppercase English letters. The length of the string is equal to n.

Output

Print one integer, denoting the minimum possible number of moves Limak can do, in order to obtain a string without a substring "VK".

Examples
input
4VKVK
output
3
input
5BVVKV
output
2
input
7VVKEVKK
output
3
input
20VKVKVVVKVOVKVQKKKVVK
output
8
input
5LIMAK
output
0
Note

In the first sample, the initial string is "VKVK". The minimum possible number of moves is 3. One optimal sequence of moves is:

  1. Swap two last letters. The string becomes "VKKV".
  2. Swap first two letters. The string becomes "KVKV".
  3. Swap the second and the third letter. The string becomes "KKVV". Indeed, this string doesn't have a substring "VK".

In the second sample, there are two optimal sequences of moves. One is "BVVKV"  →  "VBVKV"  →  "VVBKV". The other is "BVVKV"  →  "BVKVV"  →  "BKVVV".

In the fifth sample, no swaps are necessary.

分析:我们考虑按每位去构造,设f[i][j][k][which]表示现在已经用了前i个'V'前j个'K'前k个其他字符且以which这个字符结尾的最小移动距离和,很容易发现对于一个确定的结束状态,其相同类型字符之间的前后顺序从头到尾都是不变的,那么我们就可以根据这个状态来枚举下一个字符选什么,注意如果是以v结尾那么下一个字符一定不能选k.状态书n^3,转移时的处理还要O(n),一共是O(n^4).

#include <bits/stdc++.h>#define MOD 10000007using namespace std;int n,f[77][77][77][3],cnt[3],pos[3],M[80];char s[80];void up_data(int &u,int v){if(u > v) u = v;}int main(){memset(f,0x3f,sizeof(f));cin>>n;cin>>s;for(int i = 1;i <= n;i++) if(s[i-1] == 'V') M[i] = 1; else   if(s[i-1] == 'K') M[i] = 2;   else M[i] = 0;for(int i = 1;i <= n;i++) if(M[i] == 1 && f[1][0][0][1] > n*n) f[1][0][0][1] = i-1; else   if(M[i] == 2 && f[0][1][0][2] > n*n) f[0][1][0][2] = i-1;   else    if(!M[i] && f[0][0][1][0] > n*n) f[0][0][1][0] = i-1;for(int i = 0;i <= n;i++) for(int j = 0;j <= n;j++)  for(int k = 0;k <= n;k++)   if(i + j + k < n)   {   int tot = 0;memset(pos,0,sizeof(pos));         cnt[1] = i,cnt[2] = j,cnt[0] = k;        for(int d = 1;d <= n;d++)         if(cnt[M[d]]) cnt[M[d]]--;         else          {         tot++;        if(!pos[M[d]]) pos[M[d]] = tot;     }   for(int l = 0;l < 3;l++)   {   if(f[i][j][k][l] > n*n) continue;   up_data(f[i][j][k+1][0],f[i][j][k][l] + pos[0] - 1);up_data(f[i+1][j][k][1],f[i][j][k][l] + pos[1] - 1);if(l != 1) up_data(f[i][j+1][k][2],f[i][j][k][l] + pos[2] - 1);   }   }memset(cnt,0,sizeof(cnt));for(int i = 1;i <= n;i++) cnt[M[i]]++;cout<<min(min(f[cnt[1]][cnt[2]][cnt[0]][0],f[cnt[1]][cnt[2]][cnt[0]][1]),f[cnt[1]][cnt[2]][cnt[0]][2])<<endl;}


0 0
原创粉丝点击