POJ 1141-ブラケットシーケンス(間隔DP)

トピックリンク:

http://poj.org/problem?id=1141

ブラケットシーケンス
制限時間:  1000MS   メモリ制限:  65536K
提出総数:  32282   承認済み:  9321   特別裁判官

説明

次の方法で通常のブラケットシーケンスを定義しましょう 

。1。空のシーケンスは通常のシーケンスです。 
2. Sが正則列の場合、(S)と[S]は両方とも正則列です。 
3. AとBが正則列の場合、ABは正則列です。 

たとえば、次の文字シーケンスはすべて通常の角かっこシーケンスです: 

()、[]、(())、([])、()[]、()[()] 

そして次の文字シーケンスはすべてない: 

(、[、)、)(、([)]、([(] 

文字のシーケンス '('、 ')'、 '['、および ']'が指定されています。指定された文字シーケンスをサブシーケンスとして含む、可能な限り短い通常のブラケットシーケンスを見つける必要があります。ここで、文字列a1 a2 ... anは、文字列b1 b2 ... bmのサブシーケンスと呼ばれ、そのようなインデックス1 = i1 <i2 <... <in = mが存在する場合、すべての1に対してaj = bijとなります。 = j = n。

入力

入力ファイルには、最大100個の角かっこ(文字 '('、 ')'、 '['、および ']')が含まれ、それらは1行にあり、他の文字は含まれていません。

出力

可能な限り最小の長さを持ち、サブシーケンスとして指定されたシーケンスを含むいくつかの通常のブラケットシーケンスを含む1行を出力ファイルに書き込みます。

サンプル入力

([(]

サンプル出力

()[()]

//区间DP
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define maxn 1005
#define inf 0x3f3f3f3f
using namespace std;
char s[maxn];
int dp[maxn][maxn];             //dp[i][j]表示区间i~j内需要最少的字符数能够匹配
int path[maxn][maxn];           //path[i][j]是表示怎么达到dp[i][j]状态的

int peidui(char c1, char c2)
{
	if((c1=='(' && c2==')')||(c1=='['&&c2==']'))
		return 1;
	return 0;
}

//输出区间(x,y)的配对结果
void print_path(int x, int y)
{
    if(x>y)
        return;
	//只剩下一个,补上完整的
	if(x==y)
	{
		if(s[x]=='(' || s[x]==')')
			printf("()");
		else
			printf("[]");
		return;
	}
	if(path[x][y]==-1)   //s[x]和s[y]配对
	{
		printf("%c", s[x]);
		print_path(x+1, y-1);
		printf("%c", s[y]);
	}
	else
	{
		int k = path[x][y];
		print_path(x, k);
		print_path(k+1, y);
	}
}

int main()
{
	while(gets(s))
	{
		memset(dp, 0, sizeof(dp));
		int l = strlen(s);
		for(int i=0; i<l; i++)       //单个字符需要1个
			dp[i][i] = 1;
		for(int len=1; len<l; len++)
			for(int i=0; i<l-len; i++)
			{
			    int j = i+len;
				dp[i][j] = inf;
				if(peidui(s[i], s[j]))
				{
					if(dp[i+1][j-1]<dp[i][j])
						{
							dp[i][j] = dp[i+1][j-1];
							path[i][j] = -1;
						}
				}

                for(int k=i; k<j; k++)
                {
                    if(dp[i][k]+dp[k+1][j] < dp[i][j])
                    {
                        dp[i][j] = dp[i][k]+dp[k+1][j];
                        path[i][j] = k;
                    }
                }
			}
		print_path(0, l-1);
		printf("\n");
	}
	return 0;
}



おすすめ

転載: blog.csdn.net/qq_31281327/article/details/76358705