ACM PKU 1411 Brackets Sequence 动态规划

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

根据刘汝佳的推荐,这道题是“简单”的动态规划,却用了我两个多小时的时间……
还是不熟悉啊 ,呵呵 时间主要浪费在第一个思路上。

两个思路;

思路一:
int num[i][j]表示第i个字符到第j个字符需要添加的最少字符数。string after[i][j]表示操作后,第i个字符到第j个字符按照最优方案添加括号后的串。
输出after[0][len-1]
#include"stdio.h"
#include
"string.h"

char *after[100][100];
int  num[100][100];
char *str=new char[100];
int len;


char * str_bin(char* str1, char* str2) //合并字符串的函数 

int n = strlen(str1)+strlen(str2); 
char* str = new char[n+1]; 
int i = 0
while ( *str1 && *str2) 

if (*str1 < *str2) 
str[i
++= *str1++
else 
str[i
++= *str2++
}
 

if (*str1) 
while (str[i++= *str1++); 
else 
while (str[i++= *str2++); 

return str; 
}
 

void dp()
{
    
int i,j,k,z;
    
for(i=len-1;i>=0;i--)
      
for(j=i;j<=len-1;j++)
        
{
          num[i][j]
=32767;
          after[i][j]
=new char[100];
          after[i][j]
="";
      }
                            //初始化

     
    
for(i=len-1;i>=0;i--)
      
for(j=i;j<=len-1;j++)
      
{
       
if(i==j)
       
{
           num[i][j]
=1;
           
if(str[i]=='(') after[i][j]="()";
           
if(str[i]==')') after[i][j]="()";
           
if(str[i]=='[') after[i][j]="[]";
           
if(str[i]==']') after[i][j]="[]";
       }

       
else
       
{
          
               
if(str[i]=='('&&str[j]==')')          
                 
if(num[i+1][j-1]<num[i][j])
                 
{
                  num[i][j]
=num[i+1][j-1];
                  after[i][j]
='('+after[i+1][j-1]+')';
                 }

                 
else if(str[i]=='['&&str[j]==']')          
                 
if(num[i+1][j-1]<num[i][j])
                 
{
                  num[i][j]
=num[i+1][j-1];
                  after[i][j]
='['+after[i+1][j-1]+']';
                 }
              
           
              
for(k=i;k<j;k++)
                  
if(num[i][k]+num[k+1][j]<num[i][j])
          
//     if(strlen(after[i][j])>strlen(after[i][k])+strlen(after[k+1][j]) )
               {
                   num[i][j]
=num[i][k]+num[k+1][j];
                   after[i][j]
=str_bin(after[i][k],after[k+1][j]);
    
               }


       }


      }


    


}


void main()
{
    
while (scanf("%s", str) != EOF)
    
{
    len
=strlen(str);
    dp();
    printf(
"%s\n",after[0][len-1]);
    }


}

总是WA,连Sample Input里的数据都通不过。而且我char *after[][]是三维数组,太不方便了,代码看起来很乱,很不爽。
想起学C语言时候,判断括号匹配时用的是递归。那能不能在查找匹配时也用递归呢? 于是有了思路二。
     

思路二:
    int opt[i,j]表示第i个字符到第j个字符需要添加的最少字符数,状态转移方程: a[i,j]=min(a[i,k]+a[k+1,j]) 
    
#include "string.h"
#include 
"stdio.h"
char str[128];
int opt[110][110],tag[110][110]; //tag记录能否str[st]和str[end]中划分子问题,用opt[i][j]表示从str[st]到str[end]所需要插入的最小字符数

void search(int st,int end)
{
 
if(st>end) return;
 
else if(st==end){         //如果剩下最后一个字符,为之配对
  if(str[st]=='('||str[st]==')')
   printf(
"()");
  
else printf("[]");
 }

   
else{
       
if(tag[st][end]==-1){  //如果str[st]和str[end]配对(tag==-1),打印str[st]和str[end],继续搜索str[st+1]和str[end-1]
   if(str[st]=='('){
    printf(
"(");
    search(st
+1,end-1);
    printf(
")");
   }
else{
    printf(
"[");
    search(st
+1,end-1);
    printf(
"]");
   }

  }

       
else{                //如果str[st]和str[end]不配对(tag!=-1),搜索从tag分开的两个子问题
   search(st,tag[st][end]);
   search(tag[st][end]
+1,end);
  }

 }

}



void main()
{
 
int len,i,interval,j,k,s,tmp;
 
while(scanf("%s",str)!=EOF)
 
{
  len
=strlen(str);
  
for(i=0;i<len;i++)opt[i][i]=1;                            //初始化,
  for(interval=1;interval<len;interval++)                   //从间隔1个字母到间隔len-1个字母分别计算tag
   for(i=0;i+interval<len;i++
   
{
    j
=i+interval;
    tmp
=32767;
    
if(str[i]=='('&&str[j]==')'||str[i]=='['&&str[j]==']')  //如果str[i]和str[j]可以配对,问题转化为求str[i+1][j-1]的tag
     tmp=opt[i+1][j-1];
    tag[i][j]
=-1;
    
for(k=i;k<j;k++)
    
{
     
if(tmp>opt[i][k]+opt[k+1][j])
     
{
         tmp
=opt[i][k]+opt[k+1][j];
         tag[i][j]
=k;
     }

    opt[i][j]
=tmp;
    }

   }

  search(
0,len-1);
  printf(
"\n");
 }

 
return;
}

posted on 2007-09-18 03:02 流牛ζ木马 阅读(1306) 评论(2)  编辑 收藏 引用

评论

# re: ACM PKU 1411 Brackets Sequence 动态规划 2007-11-24 13:40 大隐于市

汗,老大的题号写错了吧。。。这题是1141,而不是1411。。  回复  更多评论   

# re: ACM PKU 1411 Brackets Sequence 动态规划 2009-09-17 23:33 solofancy

第二个WA吧  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2007年11月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

导航

统计

公告

MY Email/MSN :mars1021@163.com QQ : 27402040 流牛ζ木马

常用链接

留言簿(6)

随笔档案

相册

搜索

最新随笔

最新评论

阅读排行榜

评论排行榜