UVA 1626 Brackets sequence (最优矩阵链乘)

Update:

递推顺序:由小区间到大区间。
最小的区间为l == r,按照l = r + k的顺序来填表
先初始化
d(i, i) = x;
for(i, 1, n) for(j, 0, n - i) 求解d(j, j + i)

如何理解紫书上的递推方式?

1. 首先,由状态转移方程中d[i][j]的其中一个状态d[i + 1][j - 1]可以得到枚举顺序。
2. 其次,d[i][j]还可由两个子串的状态得到,而逆序枚举时所有子串的结果已经取得。
3. 对这个递推过程不应该理解成一个二维的平面,应当作为区间来考虑他的状态转移。
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
const int maxn = 105;
int d[maxn][maxn];

char s[maxn];

bool match(char a, char b) { return (a == '(' && b == ')') || (a == '[' && b == ']'); }

void dp(int n) {
    for(int i = 0; i < n; ++i)
        d[i][i + 1] = 1, d[i][i] = 0;
    for(int i = n - 2; i >= 0; --i) {
        for(int j = i + 2; j <= n; ++j) {
            int &t = d[i][j];
            t = n;
            if(match(s[i], s[j - 1])) t = min(t, d[i + 1][j - 1]);
            for(int k = i + 1; k <= j - 1; ++k) {
                t = min(t, d[i][k] + d[k][j]);
            }
        }
    }

    /*cout << "debug" << endl;
    for(int i = 0; i < n; ++i)
        for(int j = i + 1; j <= n; ++j)
            printf("i = %d, j = %d, d = %d\n", i, j, d[i][j]);
    cout << "debug" << endl;*/
}

void print(int i, int j) {
    if(i >= j) return;
    if(i == j - 1) {
        if(s[i] == '(' || s[i] == ')') printf("()");
        else printf("[]");
        return;
    }

    int ans = d[i][j];
    if(match(s[i], s[j - 1]) && ans == d[i + 1][j - 1]) {
        putchar(s[i]);
        print(i + 1, j - 1);
        putchar(s[j - 1]);
    }
    else {
        for(int k = i + 1; k < j; ++k) {
            if(ans == d[i][k] + d[k][j]) {
                print(i, k); print(k, j);
                return;
            }
        }
    }
}

int main() {
/*
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
*/
    int t;
    cin >> t;
    getchar();
    while(t--) {
        gets(s);
        gets(s);
        int len = strlen(s);
        dp(len);
        print(0, len);
        cout << endl;
        if(t) cout << endl;
        //cout << d[0][len] << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值