• HDU 2476 String painter (区间DP)


    原题地址

    题意:

    给定两个字符串s1,s2,每次可以对s1的一个区间进行操作,使其一段区间内的所有字符都变成一个字符,问最少操作数使得s1变成s2。

    题解

    (完全照搬网上题解系列)

    首先考虑由空串变成s2,dp[i][j]表示[i,j]和s2相同需要的最小步数。相比朴素地操作数j-i+1,如果s2在区间[i,j]中存在相同的字符,可以一次全部修改,减少操作数。

    枚举区间的分界点,if (s2[i]==s2[k]) dp[i][j]=dp[i+1][k]+dp[k+1][j],其中i位置的字符变化可以在k位置变化时同时完成。

    #include<bits/stdc++.h>
    
    #define clr(x,y) memset((x),(y),sizeof(x))
    
    using namespace std;
    typedef long long LL;
    
    const int maxn=100;
    
    char s1[maxn+5],s2[maxn+5];
    int dp[maxn+5][maxn+5];
    int ans[maxn+5];
    int len;
    
    void solve()
    {
        clr(dp,0);
        clr(ans,0);
    
        len=strlen(s2+1);
    
        for (int i=len;i>=0;--i)
        {
            for (int j=i;j<=len;++j)
            {
                dp[i][j]=j-i+1;
                for (int k=i;k<=j;++k)
                {
                    if (s2[i]==s2[k] && i!=k)
                        dp[i][j]=min(dp[i][j],dp[i+1][k]+dp[k+1][j]);
                    else
                        dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]);
                }
            }
        }
    
        for (int i=1;i<=len;++i)
        {
            ans[i]=dp[1][i];
            if (s1[i]==s2[i]) ans[i]=ans[i-1];
            for (int j=1;j<=i-1;++j)
            {
                ans[i]=min(ans[i],ans[j]+dp[j+1][i]);
            }
        }
    
        printf("%d
    ",ans[len]);
    }
    
    int main(void)
    {
        #ifdef ex
        freopen ("../in.txt","r",stdin);
        //freopen ("../out.txt","w",stdout);
        #endif
    
        while (scanf("%s%s",s1+1,s2+1)==2)
        {
            solve();
        }
    }

  • 相关阅读:
    [ARC080D] Prime Flip
    硬币游戏
    点分治
    OneInDark对众数的爱
    [CF838D] Airplane Arrangements
    网络流总结(转载)
    二分图最大权完美匹配(KM)
    网络流
    FWT
    FFT & NTT
  • 原文地址:https://www.cnblogs.com/123-123/p/5807510.html
Copyright © 2020-2023  润新知