标签:
http://poj.org/problem?id=1068
这道题是一道模拟的题目
题目大意呢,p代表前面的‘(‘的个数,而w代表这个括号所包括的括号的个数;
给你p,要你求w;
解题思路:
首先,你肯定要把p所对应的那一个括号序列还原出来,当然,你也没必要说用字符把()表示出来,完全就可以用0和1分别代替左括号与右括号
其次,你就应该找出哪两个括号是相匹配的。比如说(((()()()))),p为456666,第一个)所匹配的为第4个左括号,第二个所匹配的为第5个左括号,第三个所匹配的为第6个左括号
从左往右对应的右括号分别所匹配的左括号的顺序为4,5,6,3,2,1。有了这个顺序,解题就容易多了,他们包含的括号数目就是为p类型-所对应的括号数+1。
也就是说括号数分别为4-4+1,5-5+1,6-6+1,6-3+1,6-2+1,6-1+1;
这个道理就在于p代表的为‘(’的个数,而当那个‘)’匹配的正是它前面的‘(’时,也就代表着总共前面有n个左括号,而它前面的正好是第n个,所以它们肯定没有包含括号,所以只有1个括号,这是加一的目的
而如果前面有N个左括号,而它所匹配的不是第N个,那么说明肯定有几个括号是被它所包含的
1 #include <stdio.h> 2 #include <iostream> 3 #include <string.h> 4 5 using namespace std; 6 7 int ans[50],a[50],b[50],mark[50]; 8 9 10 int main() 11 { 12 int n; 13 scanf("%d",&n); 14 while(n--) 15 { 16 int m,x; 17 scanf("%d",&m); 18 a[0]=0; 19 for(int i=1;i<=m;i++) 20 scanf("%d",&a[i]); 21 memset(ans,0,sizeof(ans)); //ans还原那个原括号序列,我用0代表左括号,1代表右括号 22 memset(mark,0,sizeof(mark)); //mark使用来标记这个左括号是第几个左括号的。目的是匹配括号 23 for(int i=1;i<=m;i++) 24 ans[i+a[i]]=1; //恢复原序列 25 for(int i=1,k=1;i<=2*m;i++) 26 if(ans[i]==0) {mark[i]=k;k++;} //记录左括号是第几个左括号 27 for(int i=1,k=1;i<=2*m;i++) 28 { 29 if(ans[i]==1) 30 { 31 for(x=i;x>=1;x--) //找出它前面的第一个0,即为它所匹配的0; 32 if(ans[x]==0) break; 33 b[k]=mark[x]; //记录这个右括号是匹配第几个左括号 34 k++; 35 ans[i]=-1; //匹配过的,变化数值,以免以后再次匹配 36 ans[x]=-1; 37 } 38 } 39 for(int i=1;i<=m;i++) 40 { 41 if(i==m) printf("%d\n",a[i]-b[i]+1); 42 else printf("%d ",a[i]-b[i]+1); 43 } 44 } 45 return 0; 46 }
标签:
原文地址:http://www.cnblogs.com/Tree-dream/p/5405751.html