C ++中的布尔括号

时间:2014-12-06 06:35:42

标签: c++ dynamic-programming

布尔括号问题是计算给定二进制表达式括起来的方式的数量,以便它的计算结果为true。

我根据给出heresmall video explanation here)的解释编写了一个C ++解决方案,但它总是返回零。我的代码看起来与第一页上给出的代码非常相似(在编写我的代码之前我没有看过),但它适用于我的代码。我犯了什么错误?

#include <iostream>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;

    vector<int> vals(n);
    vector<int> ops(n - 1); //ops[n] is the operator
                             //between the nth and (n-1)th values
    char tmp;

    for(int i = 0; i < 2 * n - 1; ++i) {
        if(i % 2 == 0) {
            cin >> vals[i / 2];
        } else {
            cin >> ops[i / 2];
        }
    }

    vector<vector<int> > t(n, vector<int>(n, 0)),
                         f(n, vector<int>(n, 0));

    for(int i = 0; i < n; ++i) {
        t[i][i] = vals[i] == 1;
        f[i][i] = vals[i] == 0;
    }

    const int AND = 6, OR = 1, XOR = 4;

    for(int i = 0; i < n - 2; ++i) {
        for(int j = i + 1; j < n - 1; ++j) {
            for(int k = i; k < j; ++k) {
                cout << endl << i << " " << j << " " << k << endl;
                switch(ops[k]) {
                    case AND:
                        t[i][j] = t[i][k] * t[k + 1][j];  //T & T = T
                        f[i][j] = f[i][k] * f[k + 1][j]   //F & F = F
                                + f[i][k] * t[k + 1][j]   //F & T = F
                                + t[i][k] * f[k + 1][j];  //T & F = F

                    case OR:
                        t[i][j] = t[i][k] * t[k + 1][j]   //etc
                                + f[i][k] * t[k + 1][j]
                                + t[i][k] * f[k + 1][j];
                        f[i][j] = f[i][k] * f[k + 1][j];

                    case XOR:
                        t[i][j] = f[i][k] * t[k + 1][j]
                                + t[i][k] * f[k + 1][j];
                        f[i][j] = f[i][k] * f[k + 1][j]
                                + t[i][k] * t[k + 1][j];
                }

                for(int i = 0; i < n; ++i) {
                    for(int j = 0; j < n; ++j) {
                        cout << t[i][j] << " ";
                    }
                    cout << endl;
                }
            } //k loop
        } //j loop
    } //i loop

    cout << endl << t[0][n - 1];
}

1 个答案:

答案 0 :(得分:0)

外部的两个循环(ij)不正确。您在代码中执行的操作是从表达式的一端开始,向另一端(i循环)移动,并尝试计算从当前位置开始的越来越宽的子表达式(width { {1}},j - i循环)。问题在于,为了计算宽度为j的表达式的括号变体,您需要宽度为k且更小的子表达式的所有值,在您的解决方案中,您需要使用#39} ; t计算了(不管怎样,不是全部)。因此,您依赖于尚未计算的值并默认为k - 1,这会在这些乘法中为您提供很好的胖零。

与任何动态编程问题一样,诀窍是只有在计算了宽度0的所有相关值之后才构建宽度k 的所有值。所以,外部的两个循环看起来应该是这样的:

k - 1

请记住,这是未经测试的,未实现的代码,它只是基于我对这种情况下的动态编程问题的理解(我的理解已经被认为是错误的。时间...)。但是,它应该让你在清理工作方面有一个良好的开端。