pku 1141 Brackets Sequence

zkeqing發表於2009-10-09

http://acm.pku.edu.cn/JudgeOnline/problem?id=1141 

題目大意:給你一貫括號序列(只包含小括號和中括號),讓你找出長度最小的regular brackets sequence包含此子序列.其中的regular brackets sequence定義如下:

1)空序列是一個regular brackets sequence;

2)如果s是一個regular brackets sequence,那麼[s] 也是一個regular brackets sequence,(s)也是一個regular brackets sequence.

3)如果A,B都是regular brackets sequence,那麼AB也是一個regular brackets sequence.

例如:()、[]、()[] 、([]) 、([])()[()]都是regular brackets sequence。

而[[[、 (((((、 ([)] 則都不是regular brackets sequence。其中以“([)]”為例,包含它最小的regular brackets sequence有兩個:()[()]或者是([])[].而你只要輸出其中一個就行。

 

程式碼::

/*
我們用dst[i,j]表示i到j位置中記錄下來該到哪裡劃分,假設初始化為-1,
 
 如果a[i,j]選擇最優的時候,選擇的是a[i,k]+a[k+1,j],那麼記錄下k的位置;
 
   如果a[i,j]選擇的是a[i+1,j-1]的話,那麼保持初始值即可。
  
  這樣再根據a[0,strlen(str)-1]逐步回溯。
*/

 

 

#include<stdio.h>
#include<string.h>
int  a[110][110],dst[110][110];//dst[][]記錄下要插入的點,把每次求得最小值所取的位置都記錄下來,然後用遞迴回溯的方法去求得最小的regular brackets sequence。
char str[110];
void search(int start,int end)
{
 if (start>end) return ;
 else if(start==end)
 {
  if(str[start]=='('||str[start]==')')printf("()"); //查詢的最後一個單獨的字元,需要配對
  else printf("[]");
 }
 else
 {
  if(dst[start][end]==-1)
  {
   if(str[start]=='(')
   {
    printf("(");
    search(start+1,end-1);
    printf(")");
   }
   else
   {
    printf("[");
    search(start+1,end-1);
    printf("]");
   }
   
  }
  else
  {
   search(start,dst[start][end]);
   search(dst[start][end]+1,end);
  }
 }
}

 


int main()
{
 while(gets(str))
 {
  int len,i,j,k,s,temp,e;
  len=strlen(str);
//  memset(a,0,sizeof(a));
  for(i=0;i<len;i++)
  {
   a[i][i]=1;//表示任意一個字元都要一個對應的字元來匹配;
   a[i+1][i]=0;//a[i,j]表示從位置i到位置j所需要插入的最小字元數,
  }
  memset(dst,-1,sizeof(dst));

  for(e=1;e<len;e++)//e的初始值一定要為1,如果為0輸出的將是原陣列長度的兩倍
  {
   for(i=0;i+e<len;i++)
   {

    j=i+e;
    temp=0x7fffffff;//用來暫時記錄需要在ij之間插入的最少的字元數
    if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']')
     temp=a[i+1][j-1]; //表示ij位置是一對括號,那麼最小值就是i+1,j-1之間需要的括號數
    
    for(k=i;k<j;k++)
    {
     s=a[i][k]+a[k+1][j]; 
     if(s<temp)
     {
      temp=s;
      dst[i][j]=k; // 記錄ij之間需要插入的字元數最少時的劃分位置
     }
    }
    a[i][j]=temp; //將最小插入字元數返回給a陣列
   }
  }
  search(0,len-1); //回溯輸出
  printf("/n");
 }
 return 0;
}

相關文章