zoukankan      html  css  js  c++  java
  • UVa1630,Folding

    区间dp,记忆化搜就可以

    st为原串

    dp[p][q]存st[p]~st[q]的最优长度,f[p][q]存对应的最优串

    从(0,len-1)开始搜,f[0][len-1]为所求ans,回溯条件为p==q

    同前两个题思路极为类似,但是我发现这3个题放到一起真的非常的好,难度递进,依次难在地方就是状态转移的时候决策的寻找

    而此题的决策不是很明确,可以理解为两个决策吧(大家都这么认为= =但我不怎么赞同)

    1:当子串st[p~q]可以折叠

    2:将st[p~q]分成两段

    二者中取最短

    (其实第二个决策隐藏了一个决策,举个例子,原串AA,而压缩成2(A)显然是不对的,根据第二个决策,dp[AA]=dp[A]+dp[A]=2优于决策1)

    自己coding时遇到一个问题:

    NTTTTTNTTTTTNTTTTT

    根据决策2,会得到一种情况f[0][len-1]=2(N5(T))N5(T),怎么折叠成3(N5(T));

    若是根据决策1,那得到的结果会是3(NTTTTT);

    特殊处理嵌套会非常麻烦

    解决方法详见代码

    观察了网上其他人的代码,学到了不少东西

    coding+debug:差不多断断续续5个小时左右(但是这5个小时是比较值的,记忆化dp或者说区间dp这一方面我理解的更具体,更深刻了)

    /*
     * Author:  Bingo
     * Created Time:  2015/3/3 14:19:57
     * File Name: uva1630.cpp
     */
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <string>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <time.h>
    using namespace std;
    const int maxint = 1000000;
    int n;
    int len;
    string st;
    int dp[150][150];
    string f[150][150];//一层状态对应一个串
    int judge(int l,int r){ 
        for(int i=1;i<=(r-l+1)/2;i++){  
            if((r-l+1)%i)continue;  
            bool flag=true;  
            for(int j=l;j+i<=r;j++){  
                if(st[j]!=st[j+i]){  
                    flag=false;  
                    break;  
                }  
            }  
            if(flag)return i;  
        }  
        return false;  
    }  
    int solve(int p,int q){
        if (dp[p][q]) return dp[p][q];
        else if(p==q) {
            f[p][q]=st[p];
            dp[p][q]=1;
            return 1;
        }
        else {
            int ans=maxint;
            int res;
            int k;
            for (int i=p;i<q;i++){
                res=solve(p,i)+solve(i+1,q);
                if (ans>res){
                    ans=res;
                    k=i;
                }
            }
            f[p][q]=f[p][k]+f[k+1][q];//此时的f[p][q]是否可折叠等价于st[p] [q]是否可折叠,巧妙的解决折叠f[p][q]时提取公因式的困难 
            int t=judge(p,q);
            if (t){
                char tt[10];
                sprintf(tt,"%d",(q-p+1)/t);
                string newstr=tt+string("(")+f[p][p+t-1]+string(")");//f[p][p+t-1]是精髓所在 
                if (newstr.size()<f[p][q].size()) f[p][q]=newstr;
            } 
            dp[p][q]=f[p][q].size();
            return dp[p][q];
        }
    }
    int main () {
        while (cin>>st){
            len=st.size();
            memset(dp,0,sizeof(dp));
            solve(0,len-1);
            cout << f[0][len-1]<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Web Service简介
    初识web service
    HTTP 状态代码的完整列表
    【转】JBPM4 RepositoryService
    【转】SD和SDHC和SDXC卡的区别
    【转】PP常用TCODE
    【转】SAP会计科目表
    【转】JBPM4中 state 和 task 的不同
    【转】学习一下车险
    【转】JBPM4 TaskService
  • 原文地址:https://www.cnblogs.com/acbingo/p/4312968.html
Copyright © 2011-2022 走看看