UVA 1630 记忆化搜索

题意

输入一个字符串,折叠成一个尽量短的串。问最短可以折叠成什么样子的一个串。

题解

设dp[i][j]为字符串i到j折叠成最短的字符串后的长度,ss[i][j]为字符串i到j折叠成的最短的字符串。DFS+记忆化搜索即可。

注意事项

输入的字符串右边界为str.size()-1,需要特别注意。

代码

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define INF 1e9

using namespace std;
int dp[110][110];
string ss[110][110];
string str;

int judge(int l,int r){
    for(int i=1;i<=(r-l+1)/2;i++){
        if((r-l+1)%i!=0)
            continue;
        bool re=true;
        for(int j=l;j+i<=r;j++){
            if(str[j]!=str[j+i]){
                re=false;
                break;
            }
        }
        if(re)
            return i;
    }
    return 0;
}

int dfs(int l,int r){
    if(dp[l][r]!=-1)
        return dp[l][r];
    if(l==r){
        dp[l][r]=1;
        ss[l][r]=str[l];
        return 1;
    }
    int ans=INF;
    int k=0;
    for(int i=l;i<r;i++){
        int len=dfs(l,i)+dfs(i+1,r);
        if(len<ans){
            ans=len;
            k=i;
        }
    }
    ss[l][r]=ss[l][k]+ss[k+1][r];
    dp[l][r]=ans;

    int le=judge(l,r);
    if(le){
        bool can=true;
        for(int i=l;i<=r;i++){
            if(str[i]=='('||str[i]==')')
                can=false;
        }
        int nu=(r-l+1)/le;
        char ch[20];
        sprintf(ch,"%d",nu);
        string newstr=ch+string("(")+ss[l][l+le-1]+string(")");
        if(can&&newstr.size()<dp[l][r]){
            ss[l][r]=newstr;
            dp[l][r]=newstr.size();
        }
    }
    return dp[l][r];
}

int main()
{
    while(cin>>str){
        int r=str.size()-1;
        memset(dp,-1,sizeof(dp));
        dfs(0,r);
        cout<<ss[0][r]<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值