9.11 给定一个布尔表达式,由0、1、&、|和^等符号组成,以及一个想要的布尔结果result,实现一个函数,算出有几种括号的放法可使该表达式得出result值。

解法:

跟其他递归问题一样,此题的关键在于找出问题与子问题之间的关系。

假设函数int f(expression,result)会返回所有值为return的有效表达式的数量。我们想要算出f(1^0|0|1,true)(也即,给表达式1^0|0|1加括号使其求值为true的所有方式)。每个加括号的表达式最外层肯定有一对括号。因此,我们可以这么做:

也就是说,我们可以迭代整个表达式,将每个运算符当作第一个要加括号的运算符。

现在,又该如何计算这些内层的表达式呢,比如f((1^0)|(0|1),true)?很简单,要让这个表达式的值为true,左半部分和右半部分必有一位true。因此,这个表达式分解如下:

f((1^0) | (0|1),true)= f(1^0,true)* f(0|1,true) +

            f(1^0,false)* f(0|1,true)+

            f(1^0,true) * f(0|1,false)

对每个布尔表达式,都可以进行类似的分解:

对false结果,我们也可以执行非常类似的操作:

至此,要解决这个问题,只需反复套用这些递归关系即可。

C++实现代码:

#include<iostream>
#include<string>
using namespace std; int f(string exp,bool result,int s,int e)
{
if(s==e)
{
if(exp[s]==''&&result)
return ;
else if(exp[s]==''&&!result)
return ;
else
return ;
}
int c=;
int i;
if(result)
{
for(i=s+; i<=e; i+=)
{
if(exp[i-]=='&')
{
c+=f(exp,true,s,i-)*f(exp,true,i+,e);
}
else if(exp[i]=='|')
{
c+=f(exp,true,s,i-)*f(exp,false,i+,e);
c+=f(exp,false,s,i-)*f(exp,true,i+,e);
c+=f(exp,true,s,i-)*f(exp,true,i+,e);
}
else if(exp[i]=='^')
{
c+=f(exp,true,s,i-)*f(exp,false,i+,e);
c+=f(exp,false,s,i-)*f(exp,true,i+,e);
}
}
}
else
{
for(i=s+;i<=e;i+=)
{
if(exp[i-]=='&')
{
c+=f(exp,true,s,i-)*f(exp,false,i+,e);
c+=f(exp,false,s,i-)*f(exp,true,i+,e);
c+=f(exp,false,s,i-)*f(exp,false,i+,e);
}
else if(exp[i]=='|')
{
c+=f(exp,false,s,i-)*f(exp,false,i+,e);
}
else if(exp[i]=='^')
{
c+=f(exp,true,s,i-)*f(exp,true,i+,e);
c+=f(exp,false,s,i-)*f(exp,false,i+,e);
}
}
}
return c;
} int main()
{
string str="1^0|0&1&0|1^1^0|1|1&0&1^0|0&1&0|1^1^0|1|1&0^1^0|0&1&0|1^1^0|1|1&0^1^0|0&1&0|1^1^0|1|1&0|1|0|0";
cout<<f(str,true,,)<<endl;
}

虽然这么做可行,但不是很有效,对于同一个exp的值,他会重复算f(exp)很多次。

要解决这个问题,我们可以运用动态规划,缓存不同表达式的结果。注意,我们需要根据expression和result进行缓存。

dp C++实现代码:

#include<iostream>
#include<string>
#include<map>
using namespace std; int f(string exp,bool result,int s,int e,map<string,int> &mp)
{
string key=""+result+s+e;
if(mp.find(key)!=mp.end())
return mp[key];
if(s==e)
{
if(exp[s]==''&&result)
return ;
else if(exp[s]==''&&!result)
return ;
else
return ;
}
int c=;
int i;
if(result)
{
for(i=s+; i<=e; i+=)
{
if(exp[i-]=='&')
{
c+=f(exp,true,s,i-,mp)*f(exp,true,i+,e,mp);
}
else if(exp[i]=='|')
{
c+=f(exp,true,s,i-,mp)*f(exp,false,i+,e,mp);
c+=f(exp,false,s,i-,mp)*f(exp,true,i+,e,mp);
c+=f(exp,true,s,i-,mp)*f(exp,true,i+,e,mp);
}
else if(exp[i]=='^')
{
c+=f(exp,true,s,i-,mp)*f(exp,false,i+,e,mp);
c+=f(exp,false,s,i-,mp)*f(exp,true,i+,e,mp);
}
}
}
else
{
for(i=s+;i<=e;i+=)
{
if(exp[i-]=='&')
{
c+=f(exp,true,s,i-,mp)*f(exp,false,i+,e,mp);
c+=f(exp,false,s,i-,mp)*f(exp,true,i+,e,mp);
c+=f(exp,false,s,i-,mp)*f(exp,false,i+,e,mp);
}
else if(exp[i]=='|')
{
c+=f(exp,false,s,i-,mp)*f(exp,false,i+,e,mp);
}
else if(exp[i]=='^')
{
c+=f(exp,true,s,i-,mp)*f(exp,true,i+,e,mp);
c+=f(exp,false,s,i-,mp)*f(exp,false,i+,e,mp);
}
}
}
mp[key]=c;
return c;
} int fDP(string exp,bool result,int s,int e)
{
map<string,int> dp;
return f(exp,result,s,e,dp);
}
int main()
{
string str="1^0|0&1&0|1^1^0|1|1&0&1^0|0&1&0|1^1^0|1|1&0^1^0|0&1&0|1^1^0|1|1&0^1^0|0&1&0|1^1^0|1|1&0|1|0|0";
cout<<fDP(str,true,,)<<endl;
}

careercup-递归和动态规划 9.11的更多相关文章

  1. 《Cracking the Coding Interview》——第9章:递归和动态规划——题目11

    2014-03-21 20:20 题目:给定一个只包含‘0’.‘1’.‘|’.‘&’.‘^’的布尔表达式,和一个期望的结果(0或者1).如果允许你用自由地给这个表达式加括号来控制运算的顺序,问 ...

  2. 70. Climbing Stairs【leetcode】递归,动态规划,java,算法

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  3. 算法 递归 迭代 动态规划 斐波那契数列 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. C#递归、动态规划计算斐波那契数列

    //递归         public static long recurFib(int num)         {             if (num < 2)              ...

  5. 面试题目——《CC150》递归与动态规划

    面试题9.1:有个小孩正在上楼梯,楼梯有n个台阶,小孩一次可以上1阶.2阶或者3阶.实现一个方法,计算小孩有多少种上楼梯的方式. 思路:第4个数是前三个数之和 注意:能不能使用递归,能不能建立一个很大 ...

  6. python---通过递归和动态规划策略解决找零钱问题

    也是常见套路. # coding = utf-8 def rec_mc(coin_value_list, change, know_results): min_coins = change if ch ...

  7. Idea 02.暴力递归与动态规划(1)

    1,关键词解释 1.1 暴力递归: 1, 把问题转化为规模缩小了的同类问题的子问题 2, 有明确的不需要继续进行递归的条件(base case) 3, 有当得到了子问题的结果之后的决策过程 4, 不记 ...

  8. scramble-string——两个字符串经过树化并旋转后是否一致、递归、动态规划

    Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...

  9. OptimalSolution(1)--递归和动态规划(2)矩阵的最小路径和与换钱的最少货币数问题

    一.矩阵的最小路径和 1 3 5 9 1 4 9 18 1 4 9 18 8 1 3 4 9 9 5 8 12 5 0 6 1 14 14 5 11 12 8 8 4 0 22 22 13 15 12 ...

随机推荐

  1. Java泛型反射机制(一)

    /** * * @author Administrator * 功能:泛型的必要性(参数化类型)(安全简单) */ package com.test; import java.util.*; publ ...

  2. ANDROID_MARS学习笔记_S01原始版_008_Looper\Bundle异步消息处理

    一.流程 1.自定义Handler,重写handleMessage(Message msg),用msg得到bundle,从而得到传递过来的数据 2.开启android.os.HandlerThread ...

  3. noproguard.classes-with-local.dex

    make: *** [out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/noproguard.classes-with-loca ...

  4. 创建WCF的客户端

    How to: Create a Windows Communication Foundation Client To create a Windows Communication Foundatio ...

  5. URAL1012. K-based Numbers. Version 2

    链接 考查大数 正好拿来学习下JAVA JAVA好高端.. import java.io.*; import java.math.*; import java.text.*; import java. ...

  6. Class org.apache.struts2.json.JSONWriter can not access a member of

    异常形式: Class org.apache.struts2.json.JSONWriter can not access a member of * 或是 Class com.googlecode. ...

  7. BZOJ_1614_ [Usaco2007_Jan]_Telephone_Lines_架设电话线_(二分+最短路_Dijkstra/Spfa)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1614 分析 类似POJ_3662_Telephone_Lines_(二分+最短路) Dijks ...

  8. 纯CSS实现侧边栏/分栏高度自动相等

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=694 一.为何要分栏高 ...

  9. 使用 EPUB 制作数字图书

    基于 XML 的开放式 eBook 格式 是否需要分发文档.创建电子图书或者把喜欢的博客文章存档?EPUB 是一种开放式的数字图书规范,以常用的技术如 XML.CSS 和 XHTML 为基础,EPUB ...

  10. 使用Action、Func和Lambda表达式

    使用Action.Func和Lambda表达式 在.NET在,我们经常使用委托,委托的作用不必多说,在.NET 2.0之前,我们在使用委托之前,得自定义一个委托类型,再使用这个自定义的委托类型定义一个 ...