codeforces #288 E(区间DP)

2015-01-29 09:38:25

思路:一道很好的DP题,感谢JayYe的耐心指导~

  一开始考虑了差分约束...没想出来。。。

  考虑区间DP,关键在于dp定义,我们定义dp[i][j]为第i个~第j个括号对形成一个封闭的匹配系统的可行性(也就是说i~j个括号对已经匹配,且没有除i~j以外的括号对在其中)

  显然dp为1表示可行,0表示不可行。

  进行记忆化搜索,以[1,n]为起点开始搜索。对于每一个阶段[a,b](当前处理a~b个括号对的匹配情况)有两种情况:

  (1)第a对括号可以加在最外面,条件:len = (b-a)*2+1,l[a] <= len <= r[a],形成:( a+1,a+2,...,b),那么下一步考虑的是dp[a+1][b]

  (2)第a对括号的右括号加在中间,形成:( a+1,...a+i) a+k+1,....,b,那么下一步考虑dp[a][i]和dp[i+1][b]

  (我顺便用dp[i][j]记录下了处理区间[i,j]时第a对括号的放法,dp[i][j]==INF表示第a对括号放在最外面,dp[i][j]==0表示不可行,dp[i][j]==其他数表示加在中间)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <string>
11 #include <iostream>
12 #include <algorithm>
13 using namespace std;
14 
15 #define MEM(a,b) memset(a,b,sizeof(a))
16 #define REP(i,n) for(int i=1;i<=(n);++i)
17 #define REV(i,n) for(int i=(n);i>=1;--i)
18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i)
19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i)
20 #define MP(a,b) make_pair(a,b)
21 
22 typedef long long ll;
23 typedef pair<int,int> pii;
24 const int INF = (1 << 30) - 1;
25 
26 int n;
27 int l[605],r[605];
28 int dp[605][605];
29 char s[2300];
30 
31 bool Solve(int a,int b){
32     if(a == b){
33         if(l[a] <= 1) return true;
34         return false;
35     }
36     if(dp[a][b] != -1)
37         return dp[a][b];
38     //( a+1,a+2...b-1,b ) ,在外围加第a对括号
39     int len = (b - a) * 2 + 1;
40     if(l[a] <= len && len <= r[a]){
41         if(Solve(a + 1,b)){
42             return dp[a][b] = INF;
43         }
44     }
45     //( a+1...a+k ) ...b-1,b,在中间加第a对括号
46     FOR(i,a,b - 1){
47         if(Solve(a,i) && Solve(i + 1,b)){
48             dp[a][b] = i;
49             return true;
50         }
51     }
52     dp[a][b] = 0;
53     return false;
54 }
55 
56 void Print(int a,int b){
57     if(a == b){
58         printf("()");
59         return;
60     }
61     if(dp[a][b] == INF){
62         printf("(");
63         Print(a + 1,b);
64         printf(")");
65     }
66     else{
67         Print(a,dp[a][b]);
68         Print(dp[a][b] + 1,b);
69     }
70 }
71 
72 int main(){
73     MEM(dp,-1);
74     scanf("%d",&n);
75     REP(i,n)    scanf("%d%d",&l[i],&r[i]);
76     if(Solve(1,n)){
77         Print(1,n);
78         puts("");
79     }
80     else printf("IMPOSSIBLE\n");
81     return 0;
82 }

 

posted @ 2015-01-29 10:58  Naturain  阅读(123)  评论(0编辑  收藏  举报