UVA 1630 Folding

題目鏈接: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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章