https://www.nowcoder.com/practice/9690bd908d5b4f9b91640fa835ef6f4ftpId=101&tqId=33115&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking
给定一个只由0(假)、1(真)、&(逻辑与)、|(逻辑或)和^(异或)五种字符组成的字符串express,再给定一个布尔值desires。求出express能有多少种组合方式,可以达到desired的结果。并输出你所求出的总方案数对10^9+7取模后的值。
输出两行,第一行包含一个只有0、1、&、|和^组成的字符串。其长度小于500,第二行只有一个布尔值,代表desired。
输出一个整数,表示取模后的答案。
示例1
1^0|0|1
false
2
1^((0|0)|1)和1^(0|(0|1))可以得到false
示例2
1
false
0
时间复杂度O(n^3),空间复杂度O(n^2)。
//方法一:暴力枚举 O(n!) O(n)
//运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
//case通过率为15.00%
#include
using namespace std;
const int number=1000000007;
bool isValid(const string& exp) {
if ((exp.size() & 1) == 0) {
return false;
}
for (int i = 0; i < exp.size(); i += 2) {
if (exp[i] != '1' && exp[i] != '0') {
return false;
}
}
for (int i = 1; i < exp.size(); i += 2) {
if (exp[i] != '&' && exp[i] != '|' && exp[i] != '^') {
return false;
}
}
return true;
}
long long p(const string& exp, const string& desired, int left, int right) {
if (left == right) {
if (exp[left] == '1') {
return desired=="true" ? 1 : 0;
}
else { //exp[left]=='0'
return desired=="true" ? 0 : 1;
}
}
long long res = 0;
if (desired=="true") { //desired==true
for (int i = left + 1; i < right; i += 2) {
if (exp[i] == '&') {
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
else if (exp[i] == '|') {
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
else { //exp[i]=='^'
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
}
}
else { //desired==false
for (int i = left + 1; i < right; i += 2) {
if (exp[i] == '&') {
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
else if (exp[i] == '|') {
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
else { //exp[i]=='^'
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
}
}
return res;
}
int main() {
string exp,desired;
cin >> exp >> desired;
int n=exp.size();
if (!isValid(exp)) {
cout << 0 << endl;
}
else {
cout << p(exp, desired, 0, n - 1)%number << endl;
}
system("pause");
return 0;
}
//方法二:记忆化搜索,减支 通过
#include
using namespace std;
const int number=1000000007;
vector> memoT;
vector> memoF;
bool isValid(const string& exp) {
if ((exp.size() & 1) == 0) {
return false;
}
for (int i = 0; i < exp.size(); i += 2) {
if (exp[i] != '1' && exp[i] != '0') {
return false;
}
}
for (int i = 1; i < exp.size(); i += 2) {
if (exp[i] != '&' && exp[i] != '|' && exp[i] != '^') {
return false;
}
}
return true;
}
long long p(const string& exp, const string& desired, int left, int right) {
if (left == right) {
if (exp[left] == '1') {
return desired=="true" ? 1 : 0;
}
else { //exp[left]=='0'
return desired=="true" ? 0 : 1;
}
}
long long res = 0;
if (desired=="true") { //desired==true
if(memoT[left][right]!=-1){
return memoT[left][right];
}
for (int i = left + 1; i < right; i += 2) {
if (exp[i] == '&') {
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
else if (exp[i] == '|') {
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
else { //exp[i]=='^'
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res%=number;
}
}
memoT[left][right]=res;
}
else { //desired==false
if(memoF[left][right]!=-1){
return memoF[left][right];
}
for (int i = left + 1; i < right; i += 2) {
if (exp[i] == '&') {
res += p(exp, "true", left, i - 1)*p(exp, "false", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
else if (exp[i] == '|') {
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
else { //exp[i]=='^'
res += p(exp, "true", left, i - 1)*p(exp, "true", i + 1, right);
res += p(exp, "false", left, i - 1)*p(exp, "false", i + 1, right);
res%=number;
}
}
memoF[left][right]=res;
}
return res;
}
int main() {
string exp,desired;
cin >> exp >> desired;
int n=exp.size();
memoT=vector>(n,vector(n,-1));
memoF=vector>(n,vector(n,-1));
if (!isValid(exp)) {
cout << 0 << endl;
}
else {
cout << p(exp, desired, 0, n - 1)%number << endl;
}
system("pause");
return 0;
}
//方法三:dp O(n^3) O(n^2)
#include
using namespace std;
const int number = 1000000007;
bool isValid(const string& exp) {
if ((exp.size() & 1) == 0) { //必须为奇数
return false;
}
for (int i = 0; i < exp.size(); i += 2) {
if (exp[i] != '1' && exp[i] != '0') {
return false;
}
}
for (int i = 1; i < exp.size(); i += 2) {
if (exp[i] != '&' && exp[i] != '|' && exp[i] != '^') {
return false;
}
}
return true;
}
int main() {
string exp,desired;
cin >> exp >> desired;
if (!isValid(exp)) {
cout << 0 << endl;
return 0;
}
int n = exp.size();
vector> dpT(n, vector(n, 0));
vector> dpF(n, vector(n, 0));
for (int i = 0; i < n; i += 2) {
dpT[i][i] = (exp[i] == '1') ? 1 : 0;
dpF[i][i] = (exp[i] == '0') ? 1 : 0;
}
for (int i = 2; i < n; i += 2) {
for (int j = i - 2; j >= 0; j -= 2) {
for (int k = j; k < i; k += 2) {
if (exp[k + 1] == '&') {
dpT[j][i] += dpT[j][k] * dpT[k + 2][i];
dpF[j][i] += dpT[j][k] * dpF[k + 2][i] + dpF[j][k] * dpT[k + 2][i] + dpF[j][k] * dpF[k + 2][i];
dpT[j][i] %= number;
dpF[j][i] %= number;
}
else if (exp[k + 1] == '|') {
dpT[j][i] += dpT[j][k] * dpT[k + 2][i] + dpT[j][k] * dpF[k + 2][i] + dpF[j][k] * dpT[k + 2][i];
dpF[j][i] += dpF[j][k] * dpF[k + 2][i];
dpT[j][i] %= number;
dpF[j][i] %= number;
}
else {
dpT[j][i] += dpT[j][k] * dpF[k + 2][i] + dpF[j][k] * dpT[k + 2][i];
dpF[j][i] += dpT[j][k] * dpT[k + 2][i] + dpF[j][k] * dpF[k + 2][i];
dpT[j][i] %= number;
dpF[j][i] %= number;
}
}
}
}
if (desired=="true") {
cout << dpT[0][n - 1] << endl;
}
else {
cout << dpF[0][n - 1] << endl;
}
system("pause");
return 0;
}
注:本体输入对于C++有陷阱,C++读入bool值是0和非0,而不是true和false(用true和false输入后,bool变量输出都是0)。