给你()【】组成的序列,问你最长能构成多少个匹配的。开始的错误思路,又是思维定势,觉得应该是把区间分两半,左边dp值加右边dp值再加左边区间和右边区间凑到一起能多形成的括号数,思路是这么回事没问题,中间输出了n多中间变量才发现自己这里求错了,左边和右边凑到一起多形成的不可以用min(左边左括号的数量,右边右括号的数量),有严重的思维漏洞啊!左边左括号的可以与左边右括号匹配,右边右括号也可以和右边左括号的匹配啊,照我那么求就重复了==那怎么求啊,想了半天没想到好的求一定区间内未匹配左括号、右括号的数量方法
无奈搜题解,用深搜解决啊,深搜的参数是区间左右端点,很明显如果左端点小于等于右端点,返回0,左端点==右端点-1,若能配对,返回2,不能配对返回0.重点是更长的情况:
用左顶点或是右端点尝试与中间配对,配对成功+2,循环一圈取最大。网上都是用左顶点写的,我试着改成右端点,也对了。初始化也得改
右顶点写法:
/***************** poj2955 2016.2.19 200K 32MS C++ 1042B *****************/ #include <iostream> #include<cstdio> #include<cstring> using namespace std; int dp[102][102],len; char str[105]; int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int dfs(int l,int r) { if(dp[l][r]!=-1) return dp[l][r]; if(l>=r) { dp[l][r]=0; return 0; } if(l==r-1) { if((str[l]=='('&&str[r]==')')||(str[l]=='['&&str[r]==']')) return dp[l][r]=2; else return dp[l][r]=0; } dp[l][r]=dfs(l,r-1); for(int k=l;k<r;k++) { if((str[r]==')'&&str[k]=='(')||(str[r]==']'&&str[k]=='[')) dp[l][r]=max(dp[l][r],dfs(l,k-1)+dfs(k+1,r-1)+2); } return dp[l][r]; } int main() { // freopen("cin.txt","r",stdin); while(~scanf("%s",str)) { if(strcmp(str,"end")==0) break; len=strlen(str); for(int i=len;i>0;i--) str[i]=str[i-1]; // printf("%s",str); memset(dp,-1,sizeof(dp)); printf("%d\n",dfs(1,len)); } return 0; }左顶点写法
#include <iostream> #include<cstdio> #include<cstring> using namespace std; int dp[102][102],len; char str[105]; int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int dfs(int l,int r) { if(dp[l][r]!=-1) return dp[l][r]; if(l>=r) { dp[l][r]=0; return 0; } if(l==r-1) { if((str[l]=='('&&str[r]==')')||(str[l]=='['&&str[r]==']')) return dp[l][r]=2; else return dp[l][r]=0; } dp[l][r]=dfs(l+1,r); for(int k=l+1;k<=r;k++) { if((str[l]=='('&&str[k]==')')||(str[l]=='['&&str[k]==']')) dp[l][r]=max(dp[l][r],dfs(l+1,k-1)+dfs(k+1,r)+2); } return dp[l][r]; } int main() { // freopen("cin.txt","r",stdin); while(~scanf("%s",str)) { if(strcmp(str,"end")==0) break; len=strlen(str); for(int i=len;i>0;i--) str[i]=str[i-1]; // printf("%s",str); memset(dp,-1,sizeof(dp)); printf("%d\n",dfs(1,len)); } return 0; }