UVA 1351 UVALive 3363 String Compression

dp[i][j] 表示  i-j这一段的最小值,

那么转移方程   dp[i][j]  =  min(dp[i][i+k]+dp[i+k+1][ j]           ,(如果是i--i+k-1  这个子串的重复)min( dp[i][i+k-1]    + flag+2      )  flag 为数字的长度  所占位数  )




#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)

const int maxn = 220;
const int inf = 0x7f7f7f7f;
int dp[maxn][maxn];
string str;
int ok(int i,int j,int k)
{
    //printf("i=%d j=%d k=%d ",i,j,k);
   // cout<<str.substr(i,j-i+1)<<endl;
    string tmp=str.substr(i,k);
   // cout<<tmp<<endl;
    int n=0;
    for(i;i+k-1<=j;i+=k)
    {
       // cout<<"sub "<<str.substr(i,k)<<endl;
        if(tmp==str.substr(i,k)) n++;
        else return 0;
    }
   // int n=(j-i+1)/k;
    int res=0;
    while(n)
    {
        res++;
        n/=10;
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cin>>str;
        int len=str.length();
        for(int i=0;i<=len;i++)
        {
            for(int j=i;j<=len;j++)
            dp[i][j]=inf;
            dp[i][i]=1;
        }
        for(int i=0;i<len;i++)
        {
            for(int j=i-1;j>=0;j--)
            {
                dp[j][i]=i-j+1;
                int tmp=inf;
                for(int k=j;k<i;k++)
                {
                    tmp=min(tmp,dp[j][k]+dp[k+1][i]);
                }
                for(int k=1;k<=i-j+1;k++)
                {
                    if((i-j+1)%k==0)
                    {
                        int flag=ok(j,i,k);
                       // printf("ok i=%d j=%d f=%d\n",j,i,flag);
                        if(flag) tmp=min(tmp,dp[j][j+k-1]+flag+2);
                    }
                }
                //printf("i=%d j=%d tm=%d\n",j,i,tmp);
                dp[j][i]=min(dp[j][i],tmp);
                //printf("i=%d j=%d dp=%d\n",j,i,dp[j][i]);
            }
        }
        printf("%d\n",dp[0][len-1]);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值