UVA 1630 Folding

来源:互联网 发布:伦敦帝国学院 知乎 编辑:程序博客网 时间:2024/05/16 12:54

题目链接:http://acm.hust.edu.cn/vjudge/problem/51191


题意:给一个字符串,相同部分可以折叠,折叠可以嵌套。求最短长度的一种折叠方法。括号和数字的长度也要考虑进去。


思路:对于一个字符串,有三种策略:1、不折叠。2、本身可以折叠。3、分为两个区间子问题。


#include <cstdio>#include <cmath>#include <cstring>#include <string>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;#define rep(i,j,k) for (int i=j;i<=k;i++)#define Rrep(i,j,k) for (int i=j;i>=k;i--)#define Clean(x,y) memset(x,y,sizeof(x))const int maxn = 109;char s[maxn];int n;int dp[maxn][maxn];int type[maxn][maxn]; // 0不折叠  负数表示串自己折叠,折叠长度为值的相反数 , 正数表示分为两个区间,记录第一个区间的长度bool flag[maxn][maxn];int dfs(int l,int r);int f( int x ) //计算x的位数{    int ans = 0;    while( x ) ans++ , x/=10;    return ans;}int check( int l , int r , int &x ) //检查[l,r]是否可以折叠,并求出最短长度{    int ans = 9999;    int L = r - l + 1;    rep(len,1,L-1)        if ( L % len == 0 ) //尝试len长度的折叠        {            bool flag = true;            int p1 = l , p2 = l + len;            while( p2 <= r )            {                if ( s[p1] != s[p2] ) {flag = false;break;}                p1++ , p2++;            }            if ( flag ) //可以折叠            {                int temp = f( L / len ) + 2 + dfs( l , l + len - 1 ); //包括括号和前面的次数一共的最短长度                if ( temp < ans )                {                    ans = temp;                    x = len; //x为循环长度                }            }        }    return ans;}int dfs( int L , int R ){    if ( flag[L][R] ) return dp[L][R];    flag[L][R] = true;    if ( L == R )    {        type[L][R] = 0;        return dp[L][R] = 1;    }    int &ans = dp[L][R];    ans = R - L + 1;    type[L][R] = 0;    int x;    int temp = check(L,R,x);    if ( ans > temp )    {        ans = temp;        type[L][R] = -x;    }    int len = R - L;    rep(i,1,len)    {        temp = dfs( L , L + i - 1 ) + dfs( L + i , R );        if ( temp < ans )        {            ans = temp;            type[L][R] = i;        }    }    return dp[L][R];}void out( int l , int r ){    if ( type[l][r] == 0 )    {        rep(i,l,r) putchar(s[i]);        return;    }    if ( type[l][r] < 0 )    {        printf("%d",(r-l+1)/(-type[l][r]) );        putchar('(');        out(l,l-type[l][r]-1);        putchar(')');        return;    }    out( l , l + type[l][r] - 1 );    out( l + type[l][r] , r );}int main(){    while( gets(s+1) )    {        Clean(flag,false);        n = strlen(s+1);        dfs( 1 , n );        out( 1 , n );        puts("");    }    return 0;}



0 0
原创粉丝点击