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 ...
随机推荐
- SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-006-定义切面使用xml
一. you can also define pointcuts that can be used across multiple aspects by placing the <aop:poi ...
- Android Integer.decode()和Intger.valueof()
decode合适用来分析数字 可以分析 8进:010=>分析后为 8 10进:10=>分析后为 10 16进:#10|0X10|0x10=>分析后是 16 而valueof 只 ...
- 手势识别官方教程(2)识别常见手势用GestureDetector+手势回调接口/手势抽象类
简介 GestureDetector识别手势. GestureDetector.OnGestureListener是识别手势后的回调接口.GestureDetector.SimpleOnGesture ...
- URAL1658. Sum of Digits(DP)
链接 这题卡了挺久了 昨天试着用类似dfs的方法直接TLE在第二组 看了下题解,,发现s1,s2的范围是个幌子..100位最大的s1900 s28100 觉得s1s2太大不敢开二维.. 这样就简单了 ...
- 使用Visual Studio进行单元测试
一.使用Visual Studio进行单元测试的几个建议 1.先写单元测试(依我愚见,应该是接口先行,如果有的话) -> 测试失败 -> 以最小的改动(即编写实际代码)使测试通过(而在VS ...
- 腾讯微博OAuth2.0认证介绍
腾讯微博开放平台,是基于腾讯微博系统,为广大开发者和用户提供的开放数据分享与传播平台. 广大开发者和用户登录平台后,就可以使用平台提供的开放API接口,创建应用从微博系统获取信息,或将新的信息传播到整 ...
- 用FSM写Case,玩过没?
一.引言 测试工程师小新一是一名安卓客户端测试工程师,对于安卓客户端的功能测试.自动化测试和性能测试方面都有着非常丰富的经验.最近小新一被通知负责某二手交易APP的功能测试,在初步了解了该APP后,小 ...
- 基于Geoserver配置多图层地图以及利用uDig来进行样式配置
在GeoServer中配置多个图层的地图相对来说很容易,其步骤为: 1. 进入geoserver 2. 配置相关的FeatureTypes 3. 配置WMS内容,进入以后,主要有以下几个地方需要命名: ...
- opencv源代码
源代码都在modules文件夹下.搜索一个函数比如dft,在win7下 找到了
- 2014-5-23 s3c2440到手
( 之前的开发板是s5pv210 (contex A8)); 现在入手JZ2440......................