zoukankan      html  css  js  c++  java
  • [GMOJ6281] 串

    没有description

    可以比较显然的想出$dp_{i,j}$表示$i$到$j$全部消除的步数作为状态

    但是好像不大好转移x

    于是就考虑在状态里多记录一点信息

    $dp_{i,j,k,l}$表示$i$到$j$消除到剩下第$k$串的前$l$位的最小步数

    再设$Can_{i,j}$表示$i$到$j$全部消除的一个最小步数

    显然,$Can_{i,j}=min(dp_{i,j,k,Len[k[})+1$

    于是我们只需要考虑$dp$数组的转移即可

    $dp$数组的转移有两种

    一种是直接往后匹配一位 即$dp_{i,j,k,l}$=$min(dp_{i,j-1,k,l-1})$条件是右端点的字符和第$l$位相同

    还有一种转移是枚举段点$m$

    段点前的被消成第$k$串的前$l$位,段点后全部被消除

    即$dp_{i,j,k,l}=min(dp_{i,m-1,k,l}+Can_{m,j})$

    接下来我们就得到了一个$Can$数组

    再定义$f_{i,j}$表示前$i$个字符,用了$j$次魔法的最小保留

    然后直接转移即可

    Code:

    #pragma GCC optimize("Ofast")
    #pragma GCC optimize("inline", "fast-math", "unroll-loops", "no-stack-protector")
    #pragma GCC diagnostic error "-fwhole-program"
    #pragma GCC diagnostic error "-fcse-skip-blocks"
    #pragma GCC diagnostic error "-funsafe-loop-optimizations"
    #include <bits/stdc++.h>
    using namespace std;
    int N,M,K;
    char B[55][55];
    int Len[205];
    int Can[205][205],dp[201][201][21][11];
    int ans[205][205];
    int main(){
        freopen("string.in","r",stdin);
        freopen("string.out","w",stdout);
        char A[505];
        scanf("%d%d%d",&N,&M,&K);
        scanf("%s",A+1);
        memset(dp,63,sizeof(dp));
        memset(Can,63,sizeof(Can));
        for(int i=1;i<=N;i++){
            Can[i][i-1]=0;
            for(int j=1;j<=M;j++)
                dp[i][i-1][j][0]=0;
        }
        for (int i=1;i<=M;i++)
            scanf("%s",B[i]+1),Len[i]=strlen(B[i]+1);
        for(int len=1;len<=N;len++){
            for(int l=1;l<=N-len+1;l++){
                int r=l+len-1;
                for(int i=1;i<=M;i++){
                    for(int j=1;j<=Len[i];j++)
                        if(A[r]==B[i][j])
                            dp[l][r][i][j]=min(dp[l][r][i][j],dp[l][r-1][i][j-1]);
                    for(int j=0;j<=Len[i];j++)
                        for(int k=l;k<=r;k++)
                            if (Can[k][r]) dp[l][r][i][j]=min(dp[l][k-1][i][j]+Can[k][r],dp[l][r][i][j]);
                }
                for(int i=1;i<=M;i++)
                Can[l][r]=min(Can[l][r],dp[l][r][i][Len[i]]+1);
    
            }
        }
        for (int i=1;i<=N;i++)
            for (int j=1;j<=K;j++)
                ans[i][j]=1e9;
        for (int i=1;i<=N;i++)
            ans[i][0]=i;
        ans[1][1]=1;
        for (int i=1;i<=N;i++)
            for (int j=1;j<=K;j++){
                ans[i][j]=ans[i-1][j]+1;
                for (int k=1;k<i;k++)
                        if (j>=Can[k][i]) ans[i][j]=min(ans[i][j],ans[k-1][j-Can[k][i]]);
            }
        int anss=1e9;
        for (int i=1;i<=K;i++)
            anss=min(anss,ans[N][i]);
        cout<<anss;
        return 0;
    }
  • 相关阅读:
    关于 省赛模拟赛(迪迦桑专场)
    ZOJ3878: Convert QWERTY to Dvorak(浙江省赛2015)
    Is It A Tree?
    Escape
    关于细节
    [UE4]AnimDynamics简介
    [UE4]武器碰撞
    [UE4]CustomAnimationBlueprintNode 自定义动画蓝图节点
    百钱买白鸡
    asp.net 标准控件的重要属性
  • 原文地址:https://www.cnblogs.com/si--nian/p/11771303.html
Copyright © 2011-2022 走看看