1. 程式人生 > >POJ2955 Brackets(區間DP,括號匹配)

POJ2955 Brackets(區間DP,括號匹配)

POJ2955
首先考慮怎麼樣定義dp讓它滿足具有通過子結構來求解、
定義dp [ i ] [ j ] 為串中第 i 個到第 j 個括號的最大匹配數目
那麼我們假如知道了 i 到 j 區間的最大匹配,那麼i+1到 j+1區間的是不是就可以很簡單的得到。
那麼 假如第 i 個和第 j 個是一對匹配的括號那麼dp [ i ] [ j ] = dp [ i+1 ] [ j-1 ] + 2 ;
那麼我們只需要從小到大列舉所有 i 和 j 中間的括號數目,然後滿足匹配就用上面式子dp,然後每次更新dp [ i ] [ j ]為最大值即可。
更新最大值的方法是列舉 i 和 j 的中間值,然後讓 dp[ i ] [ j ] = max ( dp [ i ] [ j ] , dp [ i ] [ f ] + dp [ f+1 ] [ j ] ) ;
如果要求列印路徑,即輸出匹配後的括號。見

http://blog.csdn.net/y990041769/article/details/24238547詳細講解

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 120
#define inf 0x3f3f3f
int max(int a,int b){return a>b?a:b;}
int dp[N][N],i,j,k,f;
//定義dp [ i ] [ j ] 為串中第 i 個到第 j 個括號的最大匹配數目
int main(){ string s; while(cin>>s){ if(s=="end") break; memset(dp,0,sizeof(dp)); for(i=1;i<s.size ();i++){ //i是區間長度 for(j=0,k=i;k<s.size ();j++,k++){ //j是起點,k是終點,區間在滑動 if(s[j]=='('&&s[k]==')'||s[j]=='['&&s[k]==']') dp[j][k]=dp[j+1
][k-1]+2; //子集 for(f=j;f<k;f++)//f作為分割點,尋找j---k之間最大的dp[j][k] dp[j][k]=max(dp[j][k],dp[j][f]+dp[f+1][k]); } } cout<<dp[0][s.size ()-1]<<endl; } return 0; }