"DP output range of programs" Folding

Problem

Bill tried to compactly represent uppercase character sequence from "A" to "Z" folded by repeating sequences therein.

For example, a sequence showing a method is AAAAAAAAAABABABCCD 10 (A) 2 (BA) B2 (C) D. He formally defined folding sequence of characters and converting them to expand in the following ways: comprising from "A" to a sequence "Z" single character sequence is considered to be folded. Expand this sequence produces the same sequence of individual characters themselves. If the sequence S and Q is folded, the folding sequence is SQ. If S to expand S 'and Q to expand Q', to expand the SQ S'Q '.

If S is a folded sequence, X (S) is folded sequence, wherein X is an integer greater than 1 indicates a decimal. If the expanded S S ', then X (S) to expand S' is repeated X times.

According to this definition, it is easy to expand any given sequence of folding. However, Bill is more interested in the reverse transformation. He desired folded in a given sequence, such that the folded sequence obtained comprises as little as possible the number of characters.

Dolution

We set f [ i ] [ j ] f[i][j] represents [ i , j ] [i,j] minimum number of characters, set up g [ i ] [ j ] g[i][j] represents [ i , j ] [i,j] resentment.

Obviously for the interval [ i , j ] [i,j] answer must be divided into two parts:

  • Transferred from the sub-intervals; i.e. the sum of the two sub-sections can be obtained: f [ i ] [ j ] = f [ i ] [ k ] + f [ k + 1 ] [ j ] . f[i][j]=f[i][k]+f[k+1][j].
    g [ i ] [ j ] = g [ i ] [ k ] + g [ k + 1 ] [ j ] g[i][j]=g[i][k]+g[k+1][j]
  • Merge all the individual section cycle. At this festival cycle of violence can find. f [ i ] [ j ] = n in m + 2 + m i n l e n f[i][j]=num+2+minlen
    NUM represents the number of cycles section, minlen represents the minimum cycle length of the section.
  • at this time g [ i ] [ j ] = n u m + ( + m i n l e n + ) g[i][j]=num+'('+minlen+')'

This question is for our enlightenment is not necessarily objectionable DP output recursive lookups done later, when you can not answer sequence by doing record.

code show as below:

#include <bits/stdc++.h>

using namespace std;
const int N = 200;

char a[N];
string g[N][N], t[N][N];
int f[N][N], c[N][N], pre[N][N], n;

int find(int l, int r)
{
	for (int L=1;L<=r-l+1;++L) 
	{
		if ((r-l+1) % L) continue; 
		int flag = 1;
	    for (int i=l;i<=r-L;++i) 
	        if (a[i] ^ a[i+L]) {
	        	flag = 0;
	        	break;
	        }
	    if (flag == 1) return L;
	}
	return 0;
}
//寻找最小循环节 

string str(int x)
{
	int t = 0;
	int s[1000];
	string S;
	while (x > 0) s[++t] = x%10, x /= 10;
	for (int i=t;i;--i) S += s[i]+'0';
	return S;
}

int main(void)
{
	freopen("folding.in","r",stdin);
	freopen("folding.out","w",stdout);
	cin >> a+1;
	n = strlen(a+1);
	for (int i=1;i<=n;++i) {
		f[i][i] = 1;
		g[i][i] = a[i];
	}
	for (int len=2;len<=n;++len)
	    for (int i=1;i<=n-len+1;++i)
		{
			int j = i+len-1;f[i][j] = INT_MAX;
			for (int k=i;k<j;++k) 
				if (g[i][k].size() + g[k+1][j].size() < f[i][j])
	   				f[i][j] = g[i][k].size() + g[k+1][j].size(),
	   				g[i][j] = g[i][k] + g[k+1][j];
	   		int len = find(i, j);
	   		if (len == 0) continue;
	   		int num = (j-i+1) / len;
	   		string S = str(num) + '(' + g[i][i+len-1] + ')';
	   		if (S.size() < f[i][j]) 
	   			f[i][j] = S.size(), g[i][j] = S;
		} 
	cout<<g[1][n]<<endl;
	return 0;
}

Guess you like

Origin blog.csdn.net/Ronaldo7_ZYB/article/details/91887354