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;
}