zoukankan      html  css  js  c++  java
  • Uva1630 Folding

    原题链接:uva 1630 Folding

    题目大意

    给定一个字符串S,可以将其中一段元素折叠,条件是每段相同并且可以嵌套.例如可以将NEERCYESYESNEERCYESYESYES折叠成2(NEERC3(YES)).要求输出方案.

    数据范围:
    (1 leq n leq 100)

    思路

    由于n只有100,而且设计整个区间的操作.比较容易想到区间DP.
    状态:(f[l][r])表示区间[l,r]最短可以压缩到多短.
    入口:(f[l][r] = r - l + 1)即不压缩,就以自己为最终的答案.
    转移:
    转移有几种情况,分别考虑一下:

    • 直接将区间划分成两半,从两半各自拼过来.这个时候方程是(f[l][r] = min(f[l][r],f[l][k] + f[k + 1][r])其中(kin [l,r-1]).为什么不是三段四段呢?因为两段就已经包含了继续下分的各种情况了,如果三段是比较短的,那么他必然包含在某个两段里的一个最后的答案.
    • 这个区间是可以拆分的.即存在一个(m)是当前区间长度(len)的因数,并且每一段(m)长度的子串都是完全相同的,这个时候每个循环节的答案就是(f[l][l + m - 1]),而每个循环节要有(len / m)的数字在前面以及一对括号,数字可以预处理出来1~100的位数直接放进去用.总的转移方程就是(f[l][r] = min(f[l][r],f[l][l + m - 1] + numlen(len / m) + 2)
      出口:(f[l][r])

    不过这个题还要输出具体方案,那么对照着写一个(res[l][r])记录([l,r])区间能获得的最终的字符串的答案具体是谁就可以了.在转移更新答案的时候把新的答案给构造出来.

    代码

    #define _CRT_SECURE_NO_WARNINGS
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N = 125;
    int numlen[N],f[N][N],n;
    bool st[N][N];
    string s,res[N][N];
    bool check(int l,int r,int m)
    {
    	for(int i = l;i < l + m;++i)
    	{
    		for(int j = i;j <= r;j += m)
    		{
    			if(s[j] != s[i])
    				return 0;
    		}
    	}
    	return 1;
    }
    inline void _ct(int l,int r)
    {
    	for(int i = l;i <= r;++i)
    		res[l][r] += s[i];
    }
    int main()
    {
    	ios::sync_with_stdio(0);cin.tie(0);
    	while(cin >> s)
    	{
    		n = s.size();s = "#" + s;
    		for(int i = 1;i <= 9;++i)	numlen[i] = 1;
    		for(int i = 10;i <= 100;++i)	numlen[i] = 2;
    		
    		for(int len = 1;len <= n;++len)
    		{
    			for(int l = 1;l + len - 1 <= n;++l)
    			{
    				int r = l + len - 1;
    				f[l][r] = len;res[l][r] = s.substr(l,len);
    				for(int k = l;k < r;++k)	
    				{
    					if(f[l][r] > f[l][k] + f[k + 1][r])
    					{
    						f[l][r] = f[l][k] + f[k + 1][r];
    						res[l][r] = res[l][k] + res[k + 1][r];
    					}
    					
    				}
    				for(int m = 1;m < len;++m)
    				{
    					if(len % m)	continue;
    					if(check(l,r,m))	
    					{
    						if(f[l][r] > f[l][l + m - 1] + numlen[len / m] + 2)
    						{
    							f[l][r] = f[l][l + m - 1] + numlen[len / m] + 2;
    							res[l][r] = to_string(len / m) + 
    							"(" + res[l][l + m - 1] + ")";
    						}
    					}
    						
    				}
    			}
    		}
    		cout << res[1][n] << endl;
    	}
    
        return 0;
    }
    
  • 相关阅读:
    Oracle专家高级编程 第二章 服务器和文件
    Oracle专家高级编程 第一章
    Leetcode 4 寻找两个正序数组的中位数
    Leetcode 3 无重复字符的最长子串
    Leetcode 2 两数相加
    Leetcode 1 两数之和
    gitee开源许可证
    js新特性展开符的使用方式
    webpack高速配置
    JS中日期比较时斜杠与横杠的区别
  • 原文地址:https://www.cnblogs.com/HotPants/p/13492401.html
Copyright © 2011-2022 走看看