zoukankan      html  css  js  c++  java
  • 【BZOJ】1068: [SCOI2007]压缩(dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1068

    发现如果只设一维的话无法转移

    那么我们开第二维,发现对于前i个来说,如果确定了M在哪里,第i个是用R还是不用就能确定了(如果用R那么在中间一定变成了缓冲串)

    那么可以转移了

    设d[i,j]表示前i个串,最近的一个M在i的前边一个格子,的最短长度,有

    d[1,1]=1

    d[i,i]=min{d[i-1,j]}+2 //即用一次M又补上i,所以+2

    d[i,j]=d[pos,j]+1,其中pos=(i+j-1)/2,且是整数(就是确定了M找前一个R),且s[j, pos]=s[pos+1, i]

    d[i,j]=min{d[i,j], d[k, j]+i-k}

    答案就是min{d[n,i], 1<=i<=n}

    因为数据小所以直接暴力处理,也就是n^3的,n^2的话应该挺好优化的

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define pii pair<int, int>
    #define mkpii make_pair<int, int>
    #define pdi pair<double, int>
    #define mkpdi make_pair<double, int>
    #define pli pair<ll, int>
    #define mkpli make_pair<ll, int>
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
    #define printarr1(a, b) for1(_, 1, b) cout << a[_] << '	'; cout << endl
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=52, oo=0x3f3f3f3f;
    int d[N][N], n;
    char s[N];
    bool check(int i, int j) {
    	int pos=(i+j-1), k=1;
    	if(pos&1) return 0;
    	pos>>=1;
    	if(d[pos][j]>=oo) return 0;
    	for1(x, j, pos) { if(s[x]!=s[pos+k]) return 0; ++k; }
    	return 1;
    }
    int main() {
    	scanf("%s", s+1);
    	n=strlen(s+1);
    	CC(d, oo);
    	d[1][1]=1;
    	for1(i, 2, n) {
    		for1(j, 1, i-1) d[i][i]=min(d[i-1][j], d[i][i]);
    		d[i][i]+=2;
    		for1(j, 1, i-1) {
    			if(check(i, j)) d[i][j]=d[(i+j-1)>>1][j]+1;
    			for1(k, j, i-1) d[i][j]=min(d[i][j], d[k][j]+i-k);
    		}
    	}
    	int ans=oo;
    	for1(i, 1, n) ans=min(d[n][i], ans);
    	print(ans);
    	return 0;
    }
    

      


    Description

    给一个由小写字母组成的字符串,我们可以用一种简单的方法来压缩其中的重复信息。压缩后的字符串除了小写字母外还可以(但不必)包含大写字母R与M,其中M标记重复串的开始,R重复从上一个M(如果当前位置左边没有M,则从串的开始算起)开始的解压结果(称为缓冲串)。 bcdcdcdcd可以压缩为bMcdRR,下面是解压缩的过程:

     

    另一个例子是abcabcdabcabcdxyxyz可以被压缩为abcRdRMxyRz。

    Input

    输入仅一行,包含待压缩字符串,仅包含小写字母,长度为n。

    Output

    输出仅一行,即压缩后字符串的最短长度。

    Sample Input

    bcdcdcdcdxcdcdcdcd

    Sample Output

    12

    HINT

    在第一个例子中,解为aaaRa,在第二个例子中,解为bMcdRRxMcdRR。 

    【限制】 

    100%的数据满足:1<=n<=50 100%的数据满足:1<=n<=50

    Source

     
  • 相关阅读:
    MVC模式-----struts2框架(2)
    MVC模式-----struts2框架
    html的<h>标签
    jsp脚本元素
    LeetCode "Paint House"
    LeetCode "Longest Substring with At Most Two Distinct Characters"
    LeetCode "Graph Valid Tree"
    LeetCode "Shortest Word Distance"
    LeetCode "Verify Preorder Sequence in Binary Search Tree"
    LeetCode "Binary Tree Upside Down"
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4110402.html
Copyright © 2011-2022 走看看