POJ 1141

//11208462	c00h00g	1141	Accepted	428K	0MS	G++	1601B	2013-01-25 16:44:59
//其实黑书中只需要相等和分割两部分就行了。即只需要判断brac[i][j]=='()'或'[]'的情况和枚举分割点的情况
//此题黑书中已经给出了比较具体的解释,关键是如何输出,其实我们只需要使用path[i][j]来记录分割点k,然后
//递归输出就行了。这让我想到了算法导论中计算矩阵相乘最少次数的那道题目,那一题也是记录了一个分割点。
//记录了分割点,然后分别对分割点左边和右边递归调用print函数就可以了 
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define INF 0x7fffffff

char brac[105];
int dp[105][105];
int path[105][105];

void get_dp(int n){
    for(int i=1;i<=n;i++){
        dp[i][i]=1;
        dp[i][i-1]=0;
    }
    for(int len=1;len<n;len++){
        for(int i=1;i<=n-len;i++){
            int j=i+len;
            dp[i][j]=INF;
            if((brac[i]=='('&&brac[j]==')')||(brac[i]=='['&&brac[j]==']')){
                if(dp[i][j]>dp[i+1][j-1]){
                    dp[i][j]=dp[i+1][j-1];
                    path[i][j]=-1;
                }
            }
            for(int k=i;k<=j-1;k++){
                if(dp[i][j]>dp[i][k]+dp[k+1][j]){
                    dp[i][j]=dp[i][k]+dp[k+1][j];
                    path[i][j]=k;
                }
            }
        }
    }
}
void print(int i,int j){
    if(i>j) return;
    if(i==j){
        if(brac[i]=='['||brac[i]==']')
            printf("[]");
        if(brac[i]=='('||brac[i]==')')
            printf("()");
        return;
    }
    int k=path[i][j];
    if(k==-1){
        if(brac[i]=='('){
            printf("(");
            print(i+1,j-1);
            printf(")");
        }
        if(brac[i]=='['){
            printf("[");
            print(i+1,j-1);
            printf("]");
        }
    }
    else{
        print(i,k);
        print(k+1,j);
    }
}

int main(){
    while(gets(brac+1)){
        int len=strlen(brac+1);
        get_dp(len);
        //printf("%d\n",dp[1][len]);
        print(1,len);
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(POJ 1141)