careercup-递归和动态规划 9.11
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的更多相关文章
- 《Cracking the Coding Interview》——第9章:递归和动态规划——题目11
2014-03-21 20:20 题目:给定一个只包含‘0’.‘1’.‘|’.‘&’.‘^’的布尔表达式,和一个期望的结果(0或者1).如果允许你用自由地给这个表达式加括号来控制运算的顺序,问 ...
- 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 ...
- 算法 递归 迭代 动态规划 斐波那契数列 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- C#递归、动态规划计算斐波那契数列
//递归 public static long recurFib(int num) { if (num < 2) ...
- 面试题目——《CC150》递归与动态规划
面试题9.1:有个小孩正在上楼梯,楼梯有n个台阶,小孩一次可以上1阶.2阶或者3阶.实现一个方法,计算小孩有多少种上楼梯的方式. 思路:第4个数是前三个数之和 注意:能不能使用递归,能不能建立一个很大 ...
- python---通过递归和动态规划策略解决找零钱问题
也是常见套路. # coding = utf-8 def rec_mc(coin_value_list, change, know_results): min_coins = change if ch ...
- Idea 02.暴力递归与动态规划(1)
1,关键词解释 1.1 暴力递归: 1, 把问题转化为规模缩小了的同类问题的子问题 2, 有明确的不需要继续进行递归的条件(base case) 3, 有当得到了子问题的结果之后的决策过程 4, 不记 ...
- scramble-string——两个字符串经过树化并旋转后是否一致、递归、动态规划
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrin ...
- 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 ...
随机推荐
- 关于方程x^2+y^2=p (p为素数)的解问题
问题描述:对于方程,其中为素数,x,y为整数,且,输出符合条件的x,y. 分析:对于本方程,我们通过费马平方和定理知道,只有奇素数p满足这个条件时才有解. 那么当此方程有解时,解有几个呢?很明显不可能 ...
- tlplayer for ios V1.1.1加密测试版本
2014-06-22 修正稳定性. 大家还是可以从原来的下载地址下载. 此为tlplayer for ios版本,可以播放加密视频与非加密视频. 加密视频下载地址:http://blog.csdn.n ...
- Android开发UI之给ListView设置布局动画效果
1.通过JAVA代码添加,资源文件基本上不修改 XML文件,只添加了一个ListView,就不贴XML文件的代码了. java代码: public class MainActivity extends ...
- Problem A+B
Problem A+B Time Limit : 1000 MS Memory Limit : 65536 KB Description Calculate a+b Input Two ...
- BZOJ_1610_[Usaco2008_Feb]_Line连线游戏_(计算几何基础+暴力)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1610 给出n个点,问两两确定的直线中,斜率不同的共有多少条. 分析 暴力枚举直线,算出来斜率放 ...
- WeiXinMPSDK-微信C# SDK
微信C# SDK 微信公众号:Senparc.Weixin.MP.dll 微信企业号:Senparc.Weixin.QY.dl 微信开放平台:Senparc.Weixin.Open.dll 本库为.N ...
- linq中的contains条件
linq中的contains条件 在sql查询语句中,in 在linq 中用contains,并且contains前面是数组,而后面是列名,如: SELECT distinct BH FROM c ...
- 谈谈分布式事务之三: System.Transactions事务详解[上篇]
在.NET 1.x中,我们基本是通过ADO.NET实现对不同数据库访问的事务..NET 2.0为了带来了全新的事务编程模式,由于所有事务组件或者类型均定义在System.Transactions程序集 ...
- POJ 3159 Candies 差分约束dij
分析:设每个人的糖果数量是a[i] 最终就是求a[n]-a[1]的最大值 然后给出m个关系 u,v,c 表示a[u]+c>=a[v] 就是a[v]-a[u]<=c 所以对于这种情况,按照u ...
- N个数的数组求N-1个数组合乘积最大的一组
/* 编程之美题,给定N个数的数组,只能使用乘法,不使用除法,找出N-1个数的乘积最大的一组,有两种方法,方法一:采用两个数组分别保存从左向右 和从又向左的两个乘积值,然后在扫描一次,求出最大乘积,空 ...