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. OpenSSH for Windows,CopSSH

    https://www.oschina.net/p/openssh+for+windows https://www.oschina.net/p/copssh

  2. 解决VC++6.0 无法打开、无法添加工程文件

    在windows系统下,经常会遇到这样的问题:点击VC++6.0 的[文件]下的[打开]无法操作,并且无法向工程添加文件,下面详细介绍一下解决方案? 工具/原料 VC++6.0 修复工具:FileTo ...

  3. Android 内核初识(5)Zygote进程

    简介 Zygote本身是一个Native的应用程序,和驱动.内核等均无关系.Zygote是由init进程根据init.rc文件中的配置项而创建的. zygote最初的名字叫“app_process”, ...

  4. BZOJ_1607_ [Usaco2008_Dec]_Patting_Heads_轻拍牛头_(筛数)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1607 给出一组n个数,求每个数能被多少个其他的数整除. 分析 暴力一点的做法就是每个数去筛它的 ...

  5. POJ_2566_Bound_Found_(尺取法+前缀和)

    描述 http://poj.org/problem?id=2566 给出一个整数序列,并给出非负整数t,求数列中连续区间和的绝对值最接近k的区间左右端点以及这个区间和的绝对值. Bound Found ...

  6. 使用 EPUB 制作数字图书

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

  7. (转载)PHP 下 CURL 通过 POST 提交表单失败的原因之一与解决办法

    (转载)http://blog.renren.com/share/246611432/7511385884 前几天在学习使用 CURL 时遇到一个问题:在 a.php 中以 POST 方式向 b.ph ...

  8. java 写的能够响应浏览器请求的 http 服务器

    这只是一个小Demo,话几十分钟搞出来的. 不废话先上代码. 首先是服务端的 package com.cnryb; import java.io.IOException; import java.io ...

  9. boost总结之any

    boost中any库相对variant简单,any可以不限定类型,variant中对我们事先会定义好我们所需的类型,但是any无此限制,any的类型检测是在run time时.   boost::an ...

  10. [Buffalo] 一些SQL函数

    取得当前时间的函数:GETDATE() 计算时间的函数:DATEADD(datepart,number,date) 计算两个时间差额:DATEDIFF(datepart,startdate,endda ...