POJ 2955 为例。
1 for循环
/* 经典的区间DP模型--最大括号匹配数。 如果找到一对匹配的括号[xxx]oooo,就把区间分成两部分,一部分是xxx,一部分是ooo,然后以此递归直到区间长度为1或者为2. */ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1002; int n; char s[maxn]; int dp[maxn][maxn]; int max(int a,int b){ return a > b ? a : b; } void printArr(){ int i,j; for(i=0;i<n;i++){ for(j=0;j<n;j++) cout << dp[i][j] << " "; cout << endl; } cout << endl; } int main() { freopen("in.txt", "r", stdin); //freopen("//media/学习/ACM/input.txt","r",stdin); while(scanf("%s",s),s[0]!='e') { int i,j,k; n=strlen(s); for(i=0;i<n;i++) for(j=0;j<n;j++) dp[i][j]=0; for(i=n-1;i>=0;i--) { //cout << i << " "; for(j=i+1;j<=n-1;j++) { //cout << i << " "; //i是开始,j是结尾 dp[i][j]=max(dp[i+1][j],dp[i][j-1]); for(k=i+1;k<=j;k++) //k是中间 { //cout << k ; if((s[i]=='('&&s[k]==')')||(s[i]=='['&&s[k]==']')) dp[i][k]=max(dp[i][k],dp[i+1][k-1]+2); //k-1做结尾,i+1做开头 dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]); //k把【i,j】 } // cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; } } cout<<dp[0][n-1]<<endl; } return 0; }
2 是搜索+记忆
#include <iostream> #include <cstring> #include <string> #include <algorithm> #include <cstdio> using namespace std; int dp[102][102]; char s[102]; int len; int MATCH(int i,int j) { if(s[i]=='('&&s[j]==')') return 1; if(s[i]=='['&&s[j]==']') return 1; return 0; } int solve(int l,int r) { if(dp[l][r]!=-1) return dp[l][r]; if(l>=r) { return dp[l][r]=0; } int i,j; int tmp,temp1,temp2; tmp=0; for(i=l; i<=r; i++) { temp1=temp2=0; if(MATCH(l,i)) { temp1=max(temp1,solve(l+1,i-1)+1+1); } else { temp1=max(temp1,solve(l+1,i)); temp1=max(temp1,solve(l,i-1)); } if(i!=r) { temp2=solve(i+1,r); } tmp=max(tmp,temp1+temp2); } return dp[l][r]=tmp; } int main() { int i,j; while(gets(s)!=NULL&&s[0]!='e') { memset(dp,-1,sizeof(dp)); printf("%d\n",solve(0,strlen(s)-1)); } return 0; }