zoukankan      html  css  js  c++  java
  • 压缩

    题目链接:https://ac.nowcoder.com/acm/problem/20252

    如果没有M的话,是一个正常的区间dp,我们可以列出来它的转移方程
    ① dp[l][r]=min( dp[l][r] , dp[l][j] + dp[j+1][r] );
    如果当前区间(l,r)前半段和后半段相同,那就将它压缩一半然后加上一个R:
    ② dp[l][r]=min( dp[l][r] , dp[l][j] + 1 );

    但是现在有一个M,因此就再加一种情况,定义dp[l][r][0/1],表示区间(l,r)有M和没有M时的最小值。
    没有M时,我们要改一下①的式子,变成:
    ① dp[l][r][0]=min( dp[l][j][0] + r-j , dp[l][r][0]); (l<= j <=r)
    因为对于后半段(j+1,r),因为没有M,要是压缩的话,会把(l,r)整个区间都压缩,所以后半段是不能压缩的,长度就是 r-j
    前半段和后半段正好相等的时候:
    ② dp[l][r][0]=min( dp[l][r][0] , dp[l][(l+r)/2][0] + 1 );

    有M的时候,枚举m的位置:
    ③ dp[l][r][1] = min( dp[l][r][1] , min( dp[l][j][1] , dp[l][j][0] ) + 1 + min( dp[j+1][r][1] , dp[j+1][r][0] ) );

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <stack>
    #include <queue>
    #include <cmath>
    #define ll long long
    #define pi 3.1415927
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    using namespace std;
    #define _int __int128_t
    inline int read()
    {
        int x=0,f=1;
        char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
        while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=getchar();
        return f*x;
    }
    void print(int x)
    {
        if(x < 0) {putchar('-');x = -x;}
        if(x/10) print(x/10);
        putchar(x%10+'0');
    }
    int n,m;
    int dp[1005][1005][2];
    string s;
    int judge(int l,int r)
    {
        int mid=(l+r)/2;
        for(int i=l;i<=mid;++i)
            if(s[i]!=s[mid+1+i-l])
                return 0;
        return 1;
    }
    int main ()
    {
        int T,i,t,j,k,p,sum=0;
        cin>>s;
        int len=s.length();
        dp[0][0][0]=1;
        for(int i=1;i<=len;++i){
            for(int l=0;l<len-i+1;++l){
                int r=l+i-1;
                dp[l][r][0]=i;dp[l][r][1]=i;
                for(int j=l;j<=r;++j){
                    dp[l][r][0]=min(dp[l][j][0]+r-j,dp[l][r][0]);
                    dp[l][r][1]=min(dp[l][r][1],min(dp[l][j][1],dp[l][j][0])+1+min(dp[j+1][r][1],dp[j+1][r][0]));
                }
                if(i%2==0 && judge(l,r) )
                    dp[l][r][0]=min(dp[l][r][0],dp[l][(l+r)/2][0]+1);
            }
        }
        p=min(dp[0][len-1][0],dp[0][len-1][1]);
        cout<<p<<endl;
        
        return 0;
    }
  • 相关阅读:
    待解决问题集锦
    蓝桥杯--- 历届试题 连号区间数(水题)
    蓝桥杯---历届试题 翻硬币 (水题)
    nyoj 678 最小K个数之和
    hdoj 2 括号配对问题【数组模拟实现+STL实现】
    hdoj 1016 Prime Ring Problem
    nyoj 62 笨小熊
    nyoj 47 过河问题
    nyoj 456 邮票分你一半
    nyoj 171 聪明的kk
  • 原文地址:https://www.cnblogs.com/blowhail/p/13336907.html
Copyright © 2011-2022 走看看