You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class10;
// 本题测试链接 : https://leetcode-cn.com/problems/boolean-evaluation-lcci/
public class Code05_BooleanEvaluation {
public static int countEval0(String express, int desired) {
if (express == null || express.equals("")) {
return 0;
}
char[] exp = express.toCharArray();
int N = exp.length;
Info[][] dp = new Info[N][N];
Info allInfo = func(exp, 0, exp.length - 1, dp);
return desired == 1 ? allInfo.t : allInfo.f;
}
public static class Info {
public int t;
public int f;
public Info(int tr, int fa) {
t = tr;
f = fa;
}
}
// 限制:
// L...R上一定有奇数个字符
// L位置的字符和R位置的字符非0即1不能是逻辑符号
// 返回str[L...R]这一段为true的方法数和false的方法数
public static Info func(char[] str, int L, int R, Info[][] dp) {
if (dp[L][R] != null) {
return dp[L][R];
}
int t = 0;
int f = 0;
if (L == R) {
t = str[L] == '1' ? 1 : 0;
f = str[L] == '0' ? 1 : 0;
} else { // L..R >=3
// 每一个种逻辑符号split枚举的东西
// 都去试试最后结合
for (int split = L + 1; split < R; split += 2) {
Info leftInfo = func(str, L, split - 1, dp);
Info rightInfo = func(str, split + 1, R, dp);
int a = leftInfo.t;
int b = leftInfo.f;
int c = rightInfo.t;
int d = rightInfo.f;
switch (str[split]) {
case '&':
t += a * c;
f += b * c + b * d + a * d;
break;
case '|':
t += a * c + a * d + b * c;
f += b * d;
break;
case '^':
t += a * d + b * c;
f += a * c + b * d;
break;
}
}
}
dp[L][R] = new Info(t, f);
return dp[L][R];
}
public static int countEval1(String express, int desired) {
if (express == null || express.equals("")) {
return 0;
}
char[] exp = express.toCharArray();
return f(exp, desired, 0, exp.length - 1);
}
public static int f(char[] str, int desired, int L, int R) {
if (L == R) {
if (str[L] == '1') {
return desired;
} else {
return desired ^ 1;
}
}
int res = 0;
if (desired == 1) {
for (int i = L + 1; i < R; i += 2) {
switch (str[i]) {
case '&':
res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R);
break;
case '|':
res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R);
res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R);
res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R);
break;
case '^':
res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R);
res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R);
break;
}
}
} else {
for (int i = L + 1; i < R; i += 2) {
switch (str[i]) {
case '&':
res += f(str, 0, L, i - 1) * f(str, 1, i + 1, R);
res += f(str, 1, L, i - 1) * f(str, 0, i + 1, R);
res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R);
break;
case '|':
res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R);
break;
case '^':
res += f(str, 1, L, i - 1) * f(str, 1, i + 1, R);
res += f(str, 0, L, i - 1) * f(str, 0, i + 1, R);
break;
}
}
}
return res;
}
public static int countEval2(String express, int desired) {
if (express == null || express.equals("")) {
return 0;
}
char[] exp = express.toCharArray();
int N = exp.length;
int[][][] dp = new int[2][N][N];
dp[0][0][0] = exp[0] == '0' ? 1 : 0;
dp[1][0][0] = dp[0][0][0] ^ 1;
for (int i = 2; i < exp.length; i += 2) {
dp[0][i][i] = exp[i] == '1' ? 0 : 1;
dp[1][i][i] = exp[i] == '0' ? 0 : 1;
for (int j = i - 2; j >= 0; j -= 2) {
for (int k = j; k < i; k += 2) {
if (exp[k + 1] == '&') {
dp[1][j][i] += dp[1][j][k] * dp[1][k + 2][i];
dp[0][j][i] += (dp[0][j][k] + dp[1][j][k]) * dp[0][k + 2][i] + dp[0][j][k] * dp[1][k + 2][i];
} else if (exp[k + 1] == '|') {
dp[1][j][i] += (dp[0][j][k] + dp[1][j][k]) * dp[1][k + 2][i] + dp[1][j][k] * dp[0][k + 2][i];
dp[0][j][i] += dp[0][j][k] * dp[0][k + 2][i];
} else {
dp[1][j][i] += dp[0][j][k] * dp[1][k + 2][i] + dp[1][j][k] * dp[0][k + 2][i];
dp[0][j][i] += dp[0][j][k] * dp[0][k + 2][i] + dp[1][j][k] * dp[1][k + 2][i];
}
}
}
}
return dp[desired][0][N - 1];
}
}