看题或者提交点击这里哦~
题意:一个括号表达式可以按照如下的规则表示,就是每个右括号之前的左括号数。 比如(((()()()))),每个右括号之前的左括号数序列为P=4 5 6 6 6 6,而每个右括号所配对的左括号是距离他的第几个W=1 1 1 4 5 6. 现在给定P,输出W。
讲解在这里~:
首先说哪坑吧!就在那个n值那里!n (1 <= n <= 20),n是右括号(也就是单个括号的个数)。因为我们要从数组p[]着手还原原来的括号字符串s[],所以这里的n (1 <= n <= 40);
怎么还原?这里就用到了类似于尺取法(每个右括号前有多少个左括号=p[i]-p[i-1]);建议自己手动看看规律嘿嘿。
然后遍历字符串,每当遇到右括号,就回溯找前面的左括号(还要判断左括号是否已配对)
那i-j+1的差值就是与这个右括号配对的左括号的距离,因为其中已经过了已配对的括号,其中也包括已配对的右括号,所以需要(i-j+1)/2;
我觉得这个用的方法不是模拟法,而是构造法,因为是自己找的规律,并没有用到模拟括号配对。。。但是不明白为什么大家都说这是模拟法~
#include<stdio.h> #include<string.h> using namespace std; int main() { char s[42]; int p[22],w[22]; int t,book[42]={0}; scanf("%d",&t); while(t--) { int n,i,j,m=0; memset(book,0,sizeof(book)); scanf("%d",&n); p[0]=0; for(i=1;i<=n;i++) { scanf("%d",&p[i]); int temp=p[i]-p[i-1]; while(temp--) { s[m++]='('; } s[m++]=')'; } /*for(i=0;i<m;i++) printf("%c",s[i]); */ int mm=1; for(i=0;i<m;i++) { if(s[i]==')') { for(j=i-1;j>=0;j--) { if(s[j]=='('&&!book[j]) { w[mm++]=(i-j+1)/2; book[j]=1; break; } } } } for(i=1;i<mm;i++) printf("%d ",w[i]); printf("\n"); } return 0; }