前缀中缀和后缀表达式
逆波兰表达式:1)单个的数是逆波兰表达式,值为该数的值
2)形如 “运算操作符 逆波兰表达式 逆波兰表达式”,是一个逆波兰表达式,值是这两个逆波兰表达式值运算的结果。
#include <iostream>
using namespace std;
double exp() {
//读入一个逆波兰表达式,并求出其值,返回
char s[1000];//假设表达式的长度不超过1000
cin >> s;
switch (s[0]) {
case'+':
return exp() + exp();
case'-':
return exp() - exp();
case'*':
return exp() * exp();
case'/':
return exp() / exp();
default:
return atof(s);//将字符串转换为浮点型数
}
}
int main() {
cout << exp();
return 0;
}
题目中说的逆波兰表达式应该是波兰表达式(前缀表达式)
#include <iostream>
using namespace std;
int FactorValue();//因子,读入一个因子,返回其值
int TermValue();//项,读入一个项,返回其值
int ExpressionValue();//表达式,读入一个表达式,返回其值
int main() {
cout << ExpressionValue() << endl;
return 0;
}int ExpressionValue() {
int result = TermValue();//求第一项的值
bool more = true;//是否有新的项
while (more) {//
char op = cin.peek();//看一下下个输入的是什么,不取出来
if (op == '+' || op == '-') {
cin.get();//从输入中取出
int value = TermValue();//求出下个项的值
if (op == '+') {
result += value;
}
else {
result -= value;
}
}
else
more = false;
}
return result;
}
int TermValue() {
int result = FactorValue();//求第一个因子
bool more = true;//是否有新的因子
while (more) {
char op = cin.peek();//看下一个输入是什么,不取出来
if (op == '*' || op == '/') {
cin.get();//取出输入中的下一个数
int value = FactorValue();
if (op == '*') {
result *= value;
}
else
result /= value;
}
else
more = false;
}
return result;
}
int FactorValue() {
char c = cin.peek();//
int result = 0;
if (c == '(') {
cin.get();//扔去左括号
result = ExpressionValue();
cin.get();//扔去右括号
}
else {
while (isdigit(c)) {
result = result * 10 + c - '0';
cin.get();
c = cin.peek();
}
}
return result;
}
以上代码和思路参考北大教授郭炜视频讲解内容。
逆波兰表达式的值求解
待更新
放苹果
分类讨论
k>i时,
盘子多了,肯定有盘子不放苹果,且不放苹果的盘子至少有k-i个,此时把i个苹果放到k个盘子的方法数目等于把i个苹果放到i个盘子的方法数目(f(i,i))。
比如,5个苹果放到7个盘子的方法总数,等于,把5个苹果放到5个盘子的方法总数。即f(5,7) = f(5,5)
k<=i时,苹果多了,
有盘子为空的情况,那么至少有一个盘子是空的,我们一定可以先做一步,就是去掉1个盘子不放苹果,减少了盘子数目,就是说,有盘子为空,把i个苹果放到k个盘子中,盘子有空的方法总数是等于把i个苹果放到k-1个盘子中的方法总数(f(i,k-1))。没盘子为空,那么每个盘子至少放一个苹果,我们一定可以先做一步,就是给每个盘子都放一个苹果,减少了苹果数目,那么把第i个苹果放到k个盘子的放法的没有盘子为空的总数等于把i-k个盘子放到k个盘子的方法总数(f(i-k,k))。
比如,把5个苹果放到4个盘子里,情况总数,等于所有盘子都放的情况总数加上有盘子不放的情况总数的和。所有盘子都放,那么每个盘子至少放一个苹果,等于把1个苹果放到4个盘子的情况总数;有盘子不放,至少有一个盘子不放,等于把5个苹果放到3个盘子的情况总数。即f(5,4) = f(1,4)+f(5,3)
边界条件:
i = 0,没有苹果,只有1种方法,就是不放苹果(每个盘子都放0个苹果);
j = 0,没有盘子,只有0种方法,因为没有盘子可以放苹果(有苹果但是没有盘子可以给我们放苹果,有0种方法)。
#include<iostream>
using namespace std;
int f(int i, int j) {
//把i个苹果放到j个盘子的方法总数
if (i < j) {
//盘子多
return f(i, i);
}
if (i == 0){
//没有苹果- -1种放法,不放
return 1;
}
if (j == 0) {
//没有盘子 - -0种方法,无盘可放
return 0;
}
return f(i, j - 1) + f(i - j, j);//苹果多的情况
}
int main() {
int t, m, n;
cin >> t;
while (t--) {
cin >> m >> n;
cout << f(m, n) << endl;
}
return 0;
}
算24
问题分解:
#include <iostream>
#include <cmath>
using namespace std;
double a[10];
#define EPS 1e-6;
bool isZero(double x) {
return fabs(x) <= EPS;
}
bool count24(double a[], int n) {
//用数组a里的n个数,计算24
if (n == 1) {
if (isZero(a[0] - 24))
return true;
else
return false;
}
double b[10];
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {//枚举两个数的组合
int m = 0;//还剩下m个数,m=n-2
for (int k = 0; k < n; k++) {
if (k != i && k != j) {
b[m++] = a[k];//其余的数放入数组b中
}
}
b[m] = a[i] + a[j];
if (count24(b, m + 1))
return true;
b[m] = a[i] - a[j];
if (count24(b, m + 1))
return true;
b[m] = a[j] - a[i];
if (count24(b, m + 1))
return true;
b[m] = a[i] * a[j];
if (count24(b, m + 1))
return true;
if (!isZero(a[j])) {
b[m] = a[i] / a[j];
if (count24(b, m + 1))
return true;
}
if (!isZero(a[i])) {
b[m] = a[j] / a[i];
if (count24(b, m + 1))
return true;
}
}
}
return false;
}
int main() {
while (true) {
for (int i = 0; i < 4; i++) {
cin >> a[i];
}
if (a[0] == 0) {
break;
}
if (count24(a, 4))
cout << "YES" << endl;
else
cout << "NO" << endl;
}
}