zoukankan      html  css  js  c++  java
  • [BZOJ1068/Luogu2470][SCOI2007]压缩

    题目链接:

    BZOJ1068

    Luogu2470

    区间(DP)

    (f_{[l][r]})

    但是转移时如果加一个(R)则无法知道上一个(M)在什么地方。

    所以设(f_{[l][r][0/1]})表示区间([l,r]),有一个(M)在开头,中间是否有其他(M)时的最小长度。

    那么有转移方程:

    [f_{[l][r][0]}=min_{i=l}^{r-1}{f_{[l][i][0]}+r-i} ]

    由前后两段组成,后面不能有(M),所以长度不变。

    [f_{[l][r][0]}=f_{[l][(l+r)>>1][0]}+1 ]

    当区间([l,r])是两个相同子串相连时可以用(R)表示。可以暴力判断

    [f_{[l][r][1]}=min_{l=i}^{r-1}{min(f_{[l][i][0]},f_{[l][i][1]})+min(f_{[i+1][r][0]},f_{[i+1][r][1]})} ]

    直接由两段拼成,每一段必须有(M)

    时间复杂度 (O(n^3))

    #include <cstdio>
    #include <cstring>
    
    inline int Min(int a,int b){return a<b?a:b;}
    
    int n,f[55][55][2];
    char s[55];
    
    inline bool Dou(int l,int r)//判断区间[l,r]是否是两个相同子串相连
    {
    	if((r-l+1)&1)return false;
    	for(int i=l,j=(l+r+1)>>1;j<=r;++i,++j)
    		if(s[i]!=s[j])return false;
    	return true;
    }
    
    int DP(int l,int r,int m)
    {
    	if(f[l][r][m])return f[l][r][m];
    	if(l==r)return f[l][r][m]=2;
    	int Res=0x3f3f3f3f;
    	if(!m)
    	{
    		if(Dou(l,r))Res=Min(Res,DP(l,(l+r)>>1,0)+1);
    		for(int i=l;i<r;++i)Res=Min(Res,DP(l,i,0)+r-i);
    	}
    	else
    		for(int i=l;i<r;++i)
    			Res=Min(Res,Min(DP(l,i,0),DP(l,i,1))+Min(DP(i+1,r,0),DP(i+1,r,1)));
    	return f[l][r][m]=Res;
    }
    
    int main()
    {
    	scanf("%s",s+1),n=strlen(s+1);
    	printf("%d
    ",Min(DP(1,n,0),DP(1,n,1))-1);
    	return 0;
    }
    
  • 相关阅读:
    Asp.Net 之 前台绑定常用总结
    http无状态
    整理Py小demo
    RawURL
    整理的笔记
    单例模式
    DevExpress v18.1新版亮点——Analytics Dashboard篇(一)
    DevExpress v18.1新版亮点——Reporting篇(四)
    MyEclipse教程:使用UML创建模块库——第二部分(一)
    DevExpress v18.1新版亮点——Reporting篇(三)
  • 原文地址:https://www.cnblogs.com/LanrTabe/p/10197927.html
Copyright © 2011-2022 走看看