括号匹配(2)NYOJ15(简单区间dp)
括号匹配(二)NYOJ15(简单区间dp)
携程资格赛B题
好吧,连复赛都没进,511.。。。
貌似D题是因为没有用unsigned long long?
括号匹配(二)
时间限制:1000 ms | 内存限制:65535 KB
难度:6
- 描述
- 给你一个字符串,里面只包含"(",")","[","]"四种符号,请问你需要至少添加多少个括号才能使这些括号匹配起来。
如:
[]是匹配的
([])[]是匹配的
((]是不匹配的
([)]是不匹配的- 输入
-
第一行输入一个正整数N,表示测试数据组数(N<=10)
每组测试数据都只有一行,是一个字符串S,S中只包含以上所说的四种字符,S的长度不超过100 - 输出
- 对于每组测试数据都输出一个正整数,表示最少需要添加的括号的数量。每组测试输出占一行
- 样例输入
-
4 [] ([])[] ((] ([)]
- 样例输出
-
0 0 3 2
- 来源
-
《算法艺术与信息学竞赛》
开始想的是直接暴力搞,不过这样很多都不会考虑到,匹配括号是一个范围的匹配问题。会想到区间dp,dp[i][j]代表i到j之间匹配最少需要添加多少符号,如果s[i]==s[j]那么dp[i][j]=dp[i+1][j-1],然后随时更新区间之类的最小值,详见代码,dp初始化需要注意。题目地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=15AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; int dp[105][105]; char s[105]; int main() { int t,i,j,k,l; cin>>t; while(t--) { cin>>s; int len=strlen(s); for(i=0;i<len;i++) for(j=0;j<len;j++) { if(i<j) dp[i][j]=105; else if(i==j) dp[i][i]=1; else dp[i][j]=0; } for(l=1;l<len;l++) //段长度递推 { for(i=0;i<len-l;i++) { j=i+l; if((s[i]=='('&&s[j]==')')||(s[i]=='['&&s[j]==']')) dp[i][j]=min(dp[i][j],dp[i+1][j-1]); for(k=i;k<j;k++) dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]); //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; } } cout<<dp[0][len-1]<<endl; } return 0; } /* 23 [] ([])[] ((] ([)] */
旋转的二进制
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2119 Accepted Submission(s): 339Problem Description给定一个自然数M,及其二进制长度N,得到一个N位的二进制串 b1 b2 ... bN-1 bN 将该串做左旋转,即b1移到bN后面,得到一个新的二进制串: b2 b3 ... bN-1 bN b1 对新的二进制串再做左旋转,得二进制串 b3 b4 ... bN-1 bN b1 b2 重复旋转操作操作,可得N个二进制串,对这N个串排序,可得一个N*N的矩阵. 例如: 1 0 0 0 1->0 0 0 1 1->0 0 1 1 0->0 1 1 0 0->1 1 0 0 0 对它们做排序,得矩阵0 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 0 0 0 1 1 1 0 0 0
问:给出一个自然数M,及其二进制长度N,求出排序矩阵的最后一列。
对于上面的例子,给出M=3,N=5,要你的程序输出10010。
补充说明:存在自然数M的二进制表达超过N位的情况,在这种情况下,取前N次循环的二进制串排序后的最后一列即可。Input第一行有一个自然数K,代表有K行测试数据(K<=1000)。 第二行至第K+1行,每行的第一个为自然数M,第二个为二进制长度N(N<64)。Output输出K行,每行N个二进制,表示矩阵最后一列从上到下的二进制。Sample Input3 3 5 4 7 1099512709120 45Sample Output10010 1000000 110000000000000000000000000000100000000000000
还是贴上自己的搓代码吧,最近好多比赛,一直在水。。。#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<algorithm> using namespace std; char a[1005][1005]; int p[1005]; char res[1005]; char tmp[1005]; unsigned long long m; int n; int tt; int main() { int t,i,j; cin>>t; while(t--) { cin>>m>>n; tt=n; int t=0; while(m) { p[t++]=m&1; m>>=1; } //cout<<t<<" dsd"<<endl; while(t+1<=n) { p[t++]=0; } n=t; for(i=0;i<n;i++) { a[0][i]=p[n-1-i]+'0'; } a[0][n]='\0'; for(j=1;j<n;j++) { for(i=n-1;i>0;i--) { a[j][i-1]=a[j-1][i]; } a[j][n-1]=a[j-1][0]; a[j][n]='\0'; } //cout<<a[1]<<" "<<a[2]<<endl; for(i=0;i<tt;i++) for(j=i+1;j<tt;j++) { if(strcmp(a[i],a[j])>0) { strcpy(tmp,a[i]); strcpy(a[i],a[j]); strcpy(a[j],tmp); } } for(i=0;i<tt;i++) res[i]=a[i][n-1]; res[tt]='\0'; cout<<res<<endl; } return 0; }