ZOJ1463: Brackets Sequence(구간 DP)

4739 단어 dpZOJ
Let us define a regular brackets sequence in the following way: 1. Empty sequence is a regular sequence. 2. If S is a regular sequence, then (S) and [S] are both regular sequences. 3. If A and B are regular sequences, then AB is a regular sequence. For example, all of the following sequences of characters are regular brackets sequences: (), [], (()), ([]), ()[], ()[()] And all of the following character sequences are not: (, [, ), )(, ([)], ([(] Some sequence of characters '(', ')', '[', and ']' is given. You are to find the shortest possible regular brackets sequence, that contains the given character sequence as a subsequence. Here, a string a1 a2 ... an is called a subsequence of the string b1 b2 ... bm, if there exist such indices 1 = i1 < i2 < ... < in = m, that aj = bij for all 1 = j = n.
Input The input file contains at most 100 brackets (characters '(', ')', '[' and ']') that are situated on a single line without any other characters among them.
Output Write to the output file a single line that contains some regular brackets sequence that has the minimal possible length and contains the given sequence as a subsequence.
This problem contains multiple test cases!
The first line of a multiple input is an integer N, then a blank line followed by N input blocks. Each input block is in the format indicated in the problem description. There is a blank line between input blocks.
The output format consists of N output blocks. There is a blank line between output blocks.
Sample Input
1 ([(]
Sample Output ()[()] 
관건은 입력과 출력 형식, 신갱!
구간 dp, dp[i][j]는 구간 i에서 j 사이의 일치수를 나타낸다. 구간 양쪽의 문자가 딱 일치할 수 있는지, 일치 상태가 이동할 수 있다면 dp[i][j]=max(dp[i][k]+dp[k+1][j], dp[i+1][j-1]+1)가 하나 더 많아진다. 일치하지 않으면 dp[i][j]=max(dp[i][j], dp[i][k]+dp[k+1][j]]][j]])이다.
만약 양쪽이 일치할 수 있고 양쪽이 일치해서 dp값이 가장 크다면 표시해 주세요.mark[i][j]=-1, 그렇지 않으면mark[i][j]=k, 이렇게 모든 구간을 dp로 한 번 하고 DFS로 다시 찾습니다. 양쪽이 일치해서 값이 가장 크다면 이 문자를 직접 출력해서 더 작은 구간으로 검색하세요. 그렇지 않으면 두 구간을 분리해서 검색하세요[i,k][k+1,j].
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define up(i,x,y) for(i=x;i<=y;i++)
#define down(i,x,y) for(i=x;i>=y;i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define w(a) while(a)
char str[105];
int t,len,dp[105][105],mark[105][105],pos[105];
void dfs(int i,int j)
{
    if(mark[i][j]==-1)
    {
        pos[i]=pos[j]=1;
        dfs(i+1,j-1);
    }
    else if(mark[i][j]>=0)
    {
        dfs(i,mark[i][j]);
        dfs(mark[i][j]+1,j);
    }
    return;
}
int main()
{
    int l,i,j,k;
    scanf("%d%*c%*c",&t);
    while(t--)
    {
        gets(str);
        len=strlen(str);
        if(!len)
        {
            printf("
"); if(t) printf("
"); continue; } up(i,0,len-1) up(j,0,len-1) { mark[i][j]=-2; dp[i][j]=0; } mem(pos,0); i=j=l=0; w(l<len) { if(i==j) { i++,j++; if(j==len) i=0,l++,j=l; continue; } if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']')) { up(k,i,j-1) { if(dp[i][j]<dp[i][k]+dp[k+1][j]) { mark[i][j]=k; dp[i][j]=dp[i][k]+dp[k+1][j]; } } if(dp[i][j]<dp[i+1][j-1]+1) { mark[i][j]=-1; dp[i][j]=dp[i+1][j-1]+1; } } else { up(k,i,j-1) { if(dp[i][j]<dp[i][k]+dp[k+1][j]) { mark[i][j]=k; dp[i][j]=dp[i][k]+dp[k+1][j]; } } } i++,j++; if(j==len) { l++; i=0; j=l; } } dfs(0,len-1); up(i,0,len-1) { if(pos[i]==1) printf("%c",str[i]); else if(str[i]=='('||str[i]==')') printf("()"); else printf("[]"); } printf("
"); if(t) { printf("
"); getchar(); } } return 0; }

좋은 웹페이지 즐겨찾기