zoukankan      html  css  js  c++  java
  • 【CodeForces】790 C. Bear and Company 动态规划

    【题目】C. Bear and Company

    【题意】给定大写字母字符串,交换相邻字符代价为1,求最小代价使得字符串不含"VK"子串。n<=75。

    【算法】动态规划

    【题解】关键在于表示状态,我们将确定下来的前若干个固定作为状态,后面新加的字符不会进入固定的前若干个。(为了方便,非'V''K'的字符皆为‘X')

    由于相同字符显然不可能跨越,那么前若干个的有效信息只有:它是由前v个’V',前k个‘K',前x个’X'组成的,最后一个字符是否’V',即f[v][k][x][0/1]。

    转移时枚举新加入的字符,问题在于统计新加入字符前有多少未固定字符,就是加入这个字符的代价。

    假设0是'V',1是‘K',2是’X',很容易预处理p[i][0]表示第i个'V'的位置,c[i][0]表示前i个位置‘V'的数量(1和2同理),然后就很容易计算了。

    如果推不清楚可以参考代码,很好理解。

    复杂度O(n^3)。

    #include<cstdio>
    #include<cstring>
    int n,p[110][3],c[110][3],f[110][110][110][2],V,K,X;
    char s[110];
    int min(int a,int b){return a<b?a:b;}
    int r(int o,int v,int k,int x){return o-min(c[o][0],v)-min(c[o][1],k)-min(c[o][2],x);}
    int main(){
        scanf("%d%s",&n,s+1);
        for(int i=1;i<=n;i++){
            for(int j=0;j<3;j++)c[i][j]=c[i-1][j];
            if(s[i]=='V')V++,p[V][0]=i,c[i][0]++;else
            if(s[i]=='K')K++,p[K][1]=i,c[i][1]++;else
            X++,p[X][2]=i,c[i][2]++;
        }
        memset(f,0x3f,sizeof(f));
        f[0][0][0][0]=0;
        for(int i=0;i<=V;i++)
            for(int j=0;j<=K;j++)
                for(int k=0;k<=X;k++){
                    int Q=min(f[i][j][k][0],f[i][j][k][1]);
                    f[i+1][j][k][1]=min(f[i+1][j][k][1],Q+r(p[i+1][0],i+1,j,k));
                    f[i][j+1][k][0]=min(f[i][j+1][k][0],f[i][j][k][0]+r(p[j+1][1],i,j+1,k));
                    f[i][j][k+1][0]=min(f[i][j][k+1][0],Q+r(p[k+1][2],i,j,k+1));
                }
        printf("%d",min(f[V][K][X][0],f[V][K][X][1]));
        return 0;
    }
    View Code
  • 相关阅读:
    用graphviz,pygraphviz快速自动绘图
    python 实现的huffman 编码压缩,解码解压缩
    python 字符串的显示
    PKU acm 1651 multiplication puzzle
    SQL Server中的数据类型详解
    (转) treeview 的设计思路
    将英文的week 转换为中文的 简单的方法
    常用的文件对应的MIME类型:
    客户端传参问题
    绑定数据与截取的另外的一中写法
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8564472.html
Copyright © 2011-2022 走看看