POJ 1141 区间dp

来源:互联网 发布:淘宝二手市场网 编辑:程序博客网 时间:2024/06/03 15:39

括号匹配

题意:

有一串字符,就是两种括号组成,当然现在是没有匹配完全,问怎么匹配才能使得添加的括号最少!

思路:

首先括号并不一定是直接在最后添加才好,根据样例就可以看出,所以需要分区间,可是怎么分区间呢?

区间的分法肯定是从小到大分,区间分好的时候该怎么判断?

定义:

dp[i][j]
表示字符串的第i个到第j个匹配之后最少的次数,若要想得到最少肯定是分情况,当s[i] = s[j]

的时候,

dp[i][j]=dp[i1][j1]
当不同的时候就分区间,当然即使相同也要在i与j之间找到有没有更少的次数。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 105;int const INF = 0xfffffff;int n;char s[maxn];int dp[maxn][maxn];int path[maxn][maxn];void dfs(int i,int j){    if(i > j) return ;    else if(i == j) {        if(s[i] == '(' || s[i] == ')')            printf("()");        else             printf("[]");    }    else if(path[i][j] == -1) {        printf("%c",s[i]);        dfs(i+1,j-1);        printf("%c",s[j]);    }    else {        dfs(i,path[i][j]);        dfs(path[i][j] + 1,j);    }}int main(int argc, char const *argv[]){    //freopen("in.txt","r",stdin);    while(gets(s)) {        int n = strlen(s);        if(n == 0) {            printf("\n");            continue;        }        memset(dp,0,sizeof(dp));        memset(path,0,sizeof(path));        for(int i = 0;i < n; i++)             dp[i][i] = 1;        for(int l = 1;l < n; l++) {            for(int i = 0;i < n-l; i++) {                int j = i + l;                dp[i][j]  = INF;                if((s[i] == '(' && s[j] == ')') || (s[i] == '[' && s[j] == ']')) {                    dp[i][j] = dp[i+1][j-1];                    path[i][j] = -1;                }                for(int k = i;k < j; k++) {                    if(dp[i][j] > dp[i][k] + dp[k+1][j]) {                        dp[i][j] = dp[i][k] + dp[k+1][j];                        path[i][j] = k;                    }                }            }        }        dfs(0,n-1);        printf("\n");    }    return 0;}
原创粉丝点击