POJ 1141 Brackets Sequence 经典区间DP题

记忆化搜索:

View Code
#include<stdio.h>
#include<string.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000000
struct node
{
    int v, vis; // v 表示DP的值,加入的最少的括号个数,vis表示dp这一个状态是否被更新
    string s;   // 保存要输出的路径, string使用很方便,但时间相当费啊
}dp[103][103];
string s;
int dfs(int x, int y)
{
    if(dp[x][y].vis) return dp[x][y].v;
    if(x == y) 
    {
        dp[x][y].v = 1, dp[x][y].vis = 1;
        if(s[x] == '(' || s[x] == ')')
            dp[x][y].s = "()";
        else
            dp[x][y].s = "[]";
    }
    if(x > y) 
        return 0;
    if(dp[x][y].vis) return dp[x][y].v;
    int ans = inf;
    if(s[x] == '(' && s[y] == ')' || s[x] == '[' && s[y] == ']')
    {
        if(ans > dfs(x+1, y-1))
        {
            ans = dp[x+1][y-1].v;
            dp[x][y].s = s[x] + dp[x+1][y-1].s + s[y];
        }
    }
    for(int k = x; k <= y-1; k++)
    {
        if(ans > dfs(x, k) + dfs(k+1, y))
        {
            ans = dp[x][k].v + dp[k+1][y].v;
            dp[x][y].s = dp[x][k].s + dp[k+1][y].s;
        }
    }
    dp[x][y].v = ans; dp[x][y].vis = 1;
    return ans;
}

int main()
{
    while(getline(cin, s))
    {
        if(s.size()== 0)
            cout << s <<endl;
        else
        {
            for(int i = 0; i < s.size(); i++)
                for(int j = 0; j < s.size(); j++)
                    dp[i][j].vis = 0, dp[i][j].v = 0;
            dfs(0, s.size()-1);
            cout<<dp[0][s.size()-1].s<<endl;
        }
    }
    return 0;
}

递推+递归输出

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
#define inf 1000000000
string s;
int dp[103][103], f[103][103]; //f[][]数组不为-1,表示dp[i][j] 是有两段得来的,
                               //其数值表示合并成一段的中间点
void print(int i, int j)//递归输出
{
    if(i == j) 
    {
        if(s[i] == '(' || s[i] == ')') printf("()");
        else printf("[]");
        return;
    }
    if(i > j) return;
    if(f[i][j] == -1)
    {
        printf("%c", s[i]);
        print(i+1, j-1);
        printf("%c", s[j]);
    }
    else 
    {
        print(i, f[i][j]);
        print(f[i][j]+1, j);
    }
}
int main()
{
    int i, j, k;
    while(getline(cin, s))
    {
        if(!s.size()) { cout << endl; continue; }
        int len = s.size();
        for(i = 0; i < len; i++)
            for(j = 0; j < len; j++)
                if(i < j) dp[i][j] = inf;
                else if(i == j) dp[i][j] = 1;
                else dp[i][j] = 0;
        memset(f, -1, sizeof(f));
        for(int l = 2; l <= len; l++)
            for(i = 0; i+l-1 < len; i++)
            {
                j = i+l-1;
                if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
                    if(dp[i][j] > dp[i+1][j-1])
                        dp[i][j] = dp[i+1][j-1];
                for(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], f[i][j] = k;
            }
        print(0, len-1);
        puts("");
    }
    return 0;
}

递推+递推输出

View Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
#define inf 1000000000
string s;
int dp[103][103];
string f[103][103];
int main()
{
    int i, j, k;
    while(getline(cin, s))
    {
        if(!s.size()) { cout << endl; continue; }
        memset(f, 0, sizeof(f));
        int len = s.size();
        for(i = 0; i < len; i++)
            for(j = 0; j < len; j++)
                if(i < j) dp[i][j] = inf;
                else if(i == j) 
                {
                    dp[i][j] = 1;
                    if(s[i] == '(' || s[i] == ')')
                        f[i][i] = "()";
                    if(s[i] == '[' || s[i] == ']')
                        f[i][i] = "[]";
                }
                else dp[i][j] = 0;
        for(int l = 2; l <= len; l++)
            for(i = 0; i+l-1 < len; i++)
            {
                j = i+l-1;
                if(s[i] == '(' && s[j] == ')' || s[i] == '[' && s[j] == ']')
                    if(dp[i][j] > dp[i+1][j-1])
                    {
                        dp[i][j] = dp[i+1][j-1];
                        f[i][j] = s[i] + f[i+1][j-1] + s[j];
                    }
                for(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];
                        f[i][j] = f[i][k] + f[k+1][j];
                
                    }
            }
        cout << f[0][len-1] << endl;
    }
    return 0;
}

你可能感兴趣的:(POJ 1141 Brackets Sequence 经典区间DP题)