CodeForces 790C Bear and Company

CodeForces 790C Bear and Company

题目描述:

输入一个字符串,你可以进行一些操作,每次操作可以交换两个相邻的字符。问至少进行几次操作,才能使这个字符串不包含子串 VK 。

题解:

我们发现其实字符串中的字符只有三种:V ,K ,和其它的(至于是 A 、 B 、 C 还是什么其实并不影响)。

dpi,j,k,v 表示将前 i 个 V ,前 j 个 K ,前 k 个其它字符全部转移到字符串的最前面的代价, v 表示最后一个字符是不是 V 。然后大力 DP 就行。

本题 O(n4) 可做,但实际 O(n3) 就行。

题目链接: vjudge 原网站

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;

#define MAXN 100

static int N;
static int pos[3][MAXN], num[3][MAXN], dp[MAXN][MAXN][MAXN][2];
static char S[MAXN];

inline int move(int i, int j, int k, int p)
{
    return max(0, num[0][p] - i) + max(0, num[1][p] - j) + max(0, num[2][p] - k) - 1;
}

int main()
{
    scanf("%d%s", &N, S + 1);
    for (int i = 1; i <= N; i++)
    {
        num[0][i] = num[0][i-1]; 
        num[1][i] = num[1][i-1];
        num[2][i] = num[2][i-1];
        if (S[i] == 'V')
            pos[0][num[0][i]++] = i;
        else if (S[i] == 'K')
            pos[1][num[1][i]++] = i;
        else
            pos[2][num[2][i]++] = i;
    }
    memset(dp, 0x3f, sizeof(dp));
    dp[0][0][0][0] = 0;
    for (int i = 0; i <= num[0][N]; i++)
        for (int j = 0; j <= num[1][N]; j++)
            for (int k = 0; k <= num[2][N]; k++)
                for (int is_v = 0; is_v < 2; is_v++)
                {
                    if (i < num[0][N])
                        dp[i+1][j][k][1] = min(dp[i+1][j][k][1], dp[i][j][k][is_v] + move(i, j, k, pos[0][i]));
                    if (j < num[1][N] && !is_v)
                        dp[i][j+1][k][0] = min(dp[i][j+1][k][0], dp[i][j][k][is_v] + move(i, j, k, pos[1][j]));
                    if (k < num[2][N])
                        dp[i][j][k+1][0] = min(dp[i][j][k+1][0], dp[i][j][k][is_v] + move(i, j, k, pos[2][k]));
                }
    printf("%d\n", min(dp[num[0][N]][num[1][N]][num[2][N]][0], dp[num[0][N]][num[1][N]][num[2][N]][1]));
    return 0;
}

提交记录(AC / Total = 1 / 1):

Run IDRemote Run IDTime(ms)Memory(kb)ResultSubmit Time
851220225686761159680AC2017-03-21 19:29:10
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值