1. 程式人生 > >區間DP題目總結

區間DP題目總結

++ define put fir 1.0 nbsp printf 初始 hid

1:給出一個括號字符串,問這個字符串中符合規則的最長子串的長度。

【分析】區間DP要覆蓋整個區間,那麽要求所有情況的並集。

先想出狀態方程:

dp[i][j]:i ~ j區間內最大匹配數目
輸出:dp[0][n-1](從0開始)

區間DP最先想到的是就是:

1.邊界情況初始化

2.for枚舉區間長度,一般從第二個開始

3.for枚舉起點

4.直接求得終點

5.若括號匹配的情況,相當於外圍是ok的,繼續深入看內部,左端點右移&右端點左移+2(因為外圍匹配,數目+26.一般情況就是枚舉斷點k,打擂臺求匹配數目最大值

7.輸出整個區間的最大匹配數

【逆序枚舉區間長度】

技術分享圖片
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include
<stack> #include<sstream> #include<list> #include<assert.h> #include<bitset> #include<numeric> #define debug() puts("++++") #define gcd(a,b) __gcd(a,b) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define fi first #define se second #define
pb push_back #define sqr(x) ((x)*(x)) #define ms(a,b) memset(a,b,sizeof(a)) #define sz size() #define be begin() #define pu push_up #define pd push_down #define cl clear() #define lowbit(x) -x&x #define all 1,n,1 #define rep(i,x,n) for(int i=(x); i<=(n); i++) using namespace std; typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> P; const int INF = 0x3f3f3f3f; const LL LNF = 1e18; const int maxm = 1e6 + 10; const double PI = acos(-1.0); const double eps = 1e-8; const int dx[] = {-1,1,0,0,1,1,-1,-1}; const int dy[] = {0,0,1,-1,1,-1,1,-1}; int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}}; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int mod = 10056; #define inf 0x3f3f3f3f #define ll long long const int maxn = 10010; int t,n,m,a[maxn],x,y,w; int dp[110][110],ans; string s; int tot=0; /* [題意]:給出一個括號字符串,問這個字符串中符合規則的最長子串的長度。 dp[i][j]:i~j區間內最大匹配數 輸出:dp[1][n] match: dp[i][j] = dp[i+1][j-1]+2; for(k:1..j) dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]); ((())) ()()() ([]]) )[)( ([][][) end 6 6 4 0 6 */ bool match(int L,int R) { return s[L]==(&&s[R]==) || s[L]==[&&s[R]==]; } int main() { while(cin>>s) { if(s=="end") break; ms(dp,0); n=s.size(); for(int i=n-1;i>=0;i--)//枚舉區間長度 { for(int j=i+1;j<n;j++) { if(match(i,j)) dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2); for(int k=i;k<j;k++) dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]); } } printf("%d\n",dp[0][n-1]); } }
POJ - 2955 Brackets

【順序】

技術分享圖片
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<map>
#include<cctype>
#include<stack>
#include<sstream>
#include<list>
#include<assert.h>
#include<bitset>
#include<numeric>
#define debug() puts("++++")
#define gcd(a,b) __gcd(a,b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a,b,sizeof(a))
#define sz size()
#define be begin()
#define pu push_up
#define pd push_down
#define cl clear()
#define lowbit(x) -x&x
#define all 1,n,1
#define rep(i,x,n) for(int i=(x); i<=(n); i++)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> P;
const int INF = 0x3f3f3f3f;
const LL LNF = 1e18;
const int maxm = 1e6 + 10;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int dx[] = {-1,1,0,0,1,1,-1,-1};
const int dy[] = {0,0,1,-1,1,-1,1,-1};
int dir[4][2] = {{0,1},{0,-1},{-1,0},{1,0}};
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int mod = 10056;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn = 10010;
int t,n,m,a[maxn],x,y,w;
int dp[110][110],ans;
string s;
int tot=0;
/*
[題意]:給出一個括號字符串,問這個字符串中符合規則的最長子串的長度。

dp[i][j]:i~j區間內最大匹配數
輸出:dp[1][n]

match:
dp[i][j] = dp[i+1][j-1]+2;


for(k:1..j)
dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]);

((()))
()()()
([]])
)[)(
([][][)
end

6
6
4
0
6
*/
bool match(int L,int R)
{
    return s[L]==(&&s[R]==) || s[L]==[&&s[R]==];
}
int main()
{
    while(cin>>s)
    {
        if(s=="end") break;
        ms(dp,0);
        n=s.size();
        for(int l=1;l<n;l++)//枚舉區間長度
        {
            for(int i=0;i+l<n;i++)//起點
            {
                int j=i+l;//終點
                if(match(i,j))
                    dp[i][j]=max(dp[i][j],dp[i+1][j-1]+2);
                for(int k=i;k<j;k++)
                    dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);
            }
        }
        printf("%d\n",dp[0][n-1]);
    }
}
括號匹配

區間DP題目總結