zoukankan      html  css  js  c++  java
  • POJ 1141 Brackets Sequence(括号匹配二)

    题目链接:http://poj.org/problem?id=1141

    题目大意:给你一串字符串,让你补全括号,要求补得括号最少,并输出补全后的结果。

    解题思路:

    开始想的是利用相邻子区间,即dp[i+1][j]之类的方法求,像是求回文串的区间DP一样。然后花了3个多小时,GG。。。

    错误数据:

    (())(]][[)
    my:6 (()()()[][][][])
    ans:4 (())([][][][])
    括号匹配跟回文串不同,并不能通过dp[i+1][j]或者dp[i][j-1]推得dp[i][j],可能是因为回文串必须满足称性质。
    而括号匹配可能可以划分成连个任意大小的子区间而没有影响。

    然后正解跟括号匹配一差不多,因为你想啊,括号匹配一求的是最多的括号对数,把原字符串长度减一下最大括号匹配数,不就是最少需要补全的括号数了嘛,我竟然想了这么久。。。

    设dp[i][j]为[i,j]最少需要补齐的括号数,得到状态转移方程:

    if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']'){
      dp[i][j]=dp[i+1][j-1];
    }
    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]),(i=<k<j)

    然后,如果dp[i][j]由dp[i][k]和dp[i][k+1]组成,则记录path[i][j]=k,否则记为-1,最后递归输出一下就行了。

    注意:输入用while(~scanf("%s",s))会错,不知道为什么

    代码

     1 #include<cstdio>
     2 #include<cmath>
     3 #include<cctype>
     4 #include<cstring>
     5 #include<iostream>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<queue>
     9 #include<set>
    10 #include<map>
    11 #include<stack>
    12 #include<string>
    13 #define lc(a) (a<<1)
    14 #define rc(a) (a<<1|1)
    15 #define MID(a,b) ((a+b)>>1)
    16 #define fin(name)  freopen(name,"r",stdin)
    17 #define fout(name) freopen(name,"w",stdout)
    18 #define clr(arr,val) memset(arr,val,sizeof(arr))
    19 #define _for(i,start,end) for(int i=start;i<=end;i++)
    20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    21 using namespace std;
    22 typedef long long LL;
    23 const int N=1e3+5;
    24 const int INF=0x3f3f3f3f;
    25 const double eps=1e-10;
    26 
    27 int dp[N][N],path[N][N];
    28 char str[N];
    29 
    30 void print(int l,int r){
    31     if(l>=r){
    32         if(l==r){
    33             if(str[l]==')'||str[l]=='(')
    34                 printf("()");
    35             if(str[l]==']'||str[l]=='[')
    36                 printf("[]");
    37         }
    38         return;
    39     }
    40     if(path[l][r]==-1){
    41         printf("%c",str[l]);
    42         print(l+1,r-1);
    43         printf("%c",str[r]);
    44     }
    45     else{
    46         int k=path[l][r];
    47         print(l,k);
    48         print(k+1,r);
    49     }
    50 }
    51 
    52 int main(){
    53     while(gets(str)){
    54         memset(path,-1,sizeof(path));
    55         int n=strlen(str);
    56         for(int i=0;i<=n;i++){
    57             dp[i][i]=1;
    58         }
    59         for(int len=1;len<n;len++){
    60             for(int i=0;i+len<n;i++){
    61                 int j=i+len;
    62                 dp[i][j]=INF;
    63                 if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']'){
    64                     dp[i][j]=dp[i+1][j-1];
    65                 }
    66                 for(int k=i;k<j;k++){
    67                     if(dp[i][j]>dp[i][k]+dp[k+1][j]){
    68                         dp[i][j]=dp[i][k]+dp[k+1][j];
    69                         path[i][j]=k;       
    70                     }
    71                 }
    72             }
    73         }
    74         print(0,n-1);
    75         printf("
    ");
    76     }
    77     return 0;
    78 }

     附上写错的代码做个纪念,毕竟写了这么久也是有感情的。。。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cctype>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 #include<vector>
      8 #include<queue>
      9 #include<set>
     10 #include<map>
     11 #include<stack>
     12 #include<string>
     13 #define lc(a) (a<<1)
     14 #define rc(a) (a<<1|1)
     15 #define MID(a,b) ((a+b)>>1)
     16 #define fin(name)  freopen(name,"r",stdin)
     17 #define fout(name) freopen(name,"w",stdout)
     18 #define clr(arr,val) memset(arr,val,sizeof(arr))
     19 #define _for(i,start,end) for(int i=start;i<=end;i++)
     20 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
     21 using namespace std;
     22 typedef long long LL;
     23 const int N=1e3+5;
     24 const int INF=0x3f3f3f3f;
     25 const double eps=1e-10;
     26 
     27 int dp[N][N],path[N][N];
     28 char str[N];
     29 int flag[N];
     30 void print(int x,int y){
     31 
     32     if(x>=y){
     33         if(x==y)
     34             flag[x]=1;
     35         return;
     36     }
     37     int t=path[x][y];
     38     if(t==1){
     39         flag[x]=1;
     40         print(x+1,y);
     41     }
     42     if(t==2){
     43         flag[y]=1;
     44         print(x,y-1);
     45     }
     46     if(t==3){
     47         print(x+1,y-1);
     48     }
     49     if(t==4){
     50         print(x+2,y);
     51     }
     52     if(t==5){
     53         print(x,y-2);
     54     }
     55 }
     56 //[)[)]]
     57 int main(){
     58     while(gets(str)){
     59        int n=strlen(str);
     60        memset(dp,0,sizeof(dp));
     61        memset(path,-1,sizeof(path));
     62        memset(flag,0,sizeof(flag));
     63        for(int i=1;i<=n;i++){
     64             dp[i][i]=1;
     65         }
     66         for(int len=1;len<n;len++){
     67             for(int i=0;i+len<n;i++){
     68                 int j=i+len;
     69                 dp[i][j]=INF;
     70                 int t1=dp[i+1][j]+1,t2=dp[i][j-1]+1,t3=dp[i+1][j-1],t4=dp[i+2][j],t5=dp[i][j-2];
     71                 dp[i][j]=min(dp[i][j],t1);
     72                 dp[i][j]=min(dp[i][j],t2);
     73                 if(min(t1,t2)==t1)
     74                     path[i][j]=1;
     75                 else
     76                     path[i][j]=2;
     77                 if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']'&&t3<dp[i][j]){
     78                     dp[i][j]=t3;
     79                     path[i][j]=3;
     80                 }
     81                 if(str[i]=='('&&str[i+1]==')'||str[i]=='['&&str[i+1]==']'&&t4<dp[i][j]){
     82                     dp[i][j]=t4;
     83                     path[i][j]=4;
     84                 }
     85                 if(str[j]==')'&&str[j-1]=='('||str[j]==']'&&str[j-1]=='['&&t5<dp[i][j]){
     86                     dp[i][j]=t5;
     87                     path[i][j]=5;
     88                 }
     89                 if(len==5)
     90                     cout<<"i="<<i<<" j="<<j<<" "<<dp[i][j]<<" "<<path[i][j]<<endl;
     91             }
     92         }
     93         //printf("%d
    ",dp[0][n-1]);
     94         print(0,n-1);
     95         for(int i=0;i<n;i++){
     96             if(flag[i]){
     97                 if(str[i]=='(')
     98                     cout<<"()";
     99                 if(str[i]==')')
    100                     cout<<"()";
    101                 if(str[i]=='[')
    102                     cout<<"[]";
    103                 if(str[i]==']')
    104                     cout<<"[]";
    105             }
    106             else
    107                 cout<<str[i];
    108         }
    109         printf("
    ");
    110     }
    111     return 0;
    112 }
  • 相关阅读:
    HDU 6166
    codeforces 798D Mike and distribution
    Codeforces Round #409 (Div. 2) D Volatile Kite
    Codeforces Round #409 (Div. 2) C Voltage Keepsake(二分)
    HDU 4609 3-idiots(FFT计数)
    LightOJ 1236 Pairs Forming LCM(算术基本定理)
    HDU 1540 Tunnel Warfare(线段树,单点更新,区间查询)
    创建最简单的Struts2项目
    java自定义拦截器
    java拦截器和过滤器的区别
  • 原文地址:https://www.cnblogs.com/fu3638/p/8843465.html
Copyright © 2011-2022 走看看