2787:算24

总时间限制:
3000ms
内存限制:
65536kB
描述
给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。现在的问题是,是否存在一种方式使得得到的表达式的结果等于24。

这里加减乘除以及括号的运算结果和运算的优先级跟我们平常的定义一致(这里的除法定义是实数除法)。

比如,对于5,5,5,1,我们知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,对于1,1,4,2,我们怎么都不能得到24。

输入
输入数据包括多行,每行给出一组测试数据,包括4个小于10个正整数。最后一组测试数据中包括4个0,表示输入的结束,这组数据不用处理。
输出
对于每一组测试数据,输出一行,如果可以得到24,输出“YES”;否则,输出“NO”。
样例输入
5 5 5 1
1 1 4 2
0 0 0 0
样例输出
YES
NO

这里有点坑,就是算24点的时候那里double和24相等的判断,可能精度有点损失,搞了好久终于AC。

这里可以用穷举的方法来计算,但是为了练习一下递归的思想,就使用了递归来实现。

主要思路如下:

1.将四个数视为一个集合;

2.从集合中随机取两个数,通过加减乘除计算这两个数的结果,然后再将结果放回集合,这样集合就减少了一个元素;

3.重复2的步骤,直到集合中只剩下一个元素为止;

4.查看最后一个元素是否有是24来得出结果。

代码写的有点垃圾,将就记录一下,有时间再改进一下。

在main函数中通过四个循环来对输入进行全排列。

#include <stdio.h>
#include <iostream>
#include <cmath>
#include <string.h>
using namespace std;double a[4];
int c[4];
int b[4];
char cal_opt[4] = {'+', '-', '*', '/'};
bool flag = false;
bool selected[4];
bool visited[4];double cal(double a, double b, char opt) {if (opt == cal_opt[0])return a + b;else if (opt == cal_opt[1])return a - b;else if (opt == cal_opt[2])return a * b;else if (opt == cal_opt[3])return a / b;return 0.0;
}void calculate(int count) {double result;if (count == 1) {for (int i = 0; i < 4; ++i) {if (!visited[i]) {result = a[i];break;}}if (fabs(result - 24.0) < 0.000001) {cout << "YES" << endl;flag = true;}return;}double left, right;for (int i = 0; i < 3; ++i) {if (visited[i])continue;for (int k = i + 1; k < 4; ++ k) {if (visited[k])continue;left = a[i];right = a[k];for (int j = 0; j < 4; ++j) {if (a[k] == 0 && j == 3) // 除法不能除0continue;result = cal(a[i], a[k], cal_opt[j]);a[i] = result;visited[k] = 1;calculate(--count);if (flag)goto here;a[i] = left;a[k] = right;visited[k] = 0;++count;}}}
here:return;
}int main() {while (true) {bool is_end = true;for (int i = 0; i < 4; ++i) {cin >> b[i];if (b[i] != 0)is_end = false;}if (is_end)break;// 生成一个全排列memset(selected, 0, sizeof selected);memset(visited, 0, sizeof visited);flag = false;for (int i = 0; i < 4; ++i) {if (selected[i])continue;selected[i] = 1;a[0] = b[i];for (int j = 0; j < 4; ++j) {if (selected[j])continue;selected[j] = 1;a[1] = b[j];for (int k = 0; k < 4; ++k) {if (selected[k])continue;selected[k] = 1;a[2] = b[k];for (int l = 0; l < 4; ++l) {if (selected[l])continue;selected[l] = 1;a[3] = b[l];calculate(4);if (flag)goto here;selected[l] = 0;}selected[k] = 0;}selected[j] = 0;}selected[i] = 0;}here:if (!flag)cout << "NO" << endl;}return 0;
}

下面这段代码是给出算24点表达式的,包括了加括号过程的恢复,使用了stack和双向队列的数据结构来完成。下面的代码没有经过充分的测试,仅记录一下。

#include <iostream>
#include <stack>
#include <deque>
#include <string>
using namespace std;double a[4];
double b[4];
char cal_opt[4] = {'+', '-', '*', '/'};
stack<double> mstack;
deque<double> mdeque;
bool flag = false;
bool selected[4];
bool visited[4];double cal(double a, double b, char opt) {if (opt == cal_opt[0])return a + b;else if (opt == cal_opt[1])return a - b;else if (opt == cal_opt[2])return a * b;else if (opt == cal_opt[3])return a / b;return 0.0;
}void calculate(int count) {double result;if (count == 1) {for (int i = 0; i < 4; ++i) {if (!visited[i]) {result = a[i];break;}}if (result == 24.0) {
//            cout << "24" << endl;stack<double> result_stack;stack<string> string_stack;while (!mdeque.empty()) {char x[100] = {0};double left = mdeque.front();
//                cout << left << endl;mdeque.pop_front();double right = mdeque.front();
//                cout << right << endl;mdeque.pop_front();char opt = (char) mdeque.front();
//                cout << opt << endl;mdeque.pop_front();double temp = cal(left, right, opt);if (!result_stack.empty()) {if (string_stack.size() == 2){string r = string_stack.top();string_stack.pop();string l = string_stack.top();string_stack.pop();r = l + opt + r;string_stack.push(r);} else if (left == result_stack.top()) {sprintf(x, "%c%d", opt, (int)right);string r(x);if ((opt == '+' || opt == '-') && !mdeque.empty())r = "(" + string_stack.top() + r + ")";elser = string_stack.top() + r;string_stack.pop();string_stack.push(r);} else if (right == result_stack.top()) {sprintf(x, "%d%c", (int)left, opt);string r(x);if ((opt == '+' || opt == '-') && !mdeque.empty())r = "(" + r + string_stack.top() + ")";elser = r + string_stack.top();string_stack.pop();string_stack.push(r);} else {result_stack.push(temp);if (opt == '+' || opt == '-')sprintf(x, "(%d%c%d)", (int)left, opt, (int)right);elsesprintf(x, "%d%c%d", (int)left, opt, (int)right);string r(x);string_stack.push(r);}result_stack.push(temp);} else {if (opt == '+' || opt == '-')sprintf(x, "(%d%c%d)", (int)left, opt, (int)right);elsesprintf(x, "%d%c%d", (int)left, opt, (int)right);string r(x);result_stack.push(temp);string_stack.push(r);}}flag = true;cout << string_stack.top() << endl;}return;}double left, right;for (int i = 0; i < 3; ++i) {if (flag)break;
//        if (a[i] == -1.0)
//            continue;if (visited[i])continue;for (int k = i + 1; k < 4; ++ k) {if (flag)break;
//            if (a[k] == -1.0)
//                continue;if (visited[i])continue;left = a[i];right = a[k];for (int j = 0; j < 4; ++j) {if (a[k] == 0 && j == 3) // 除法不能除0continue;mdeque.push_back(a[i]);mdeque.push_back(a[k]);mdeque.push_back(cal_opt[j]);result = cal(a[i], a[k], cal_opt[j]);a[i] = result;visited[k] = 1;calculate(--count);if (flag)break;mdeque.pop_back();mdeque.pop_back();mdeque.pop_back();visited[k] = 0;a[i] = left;a[k] = right;++count;}}}
}int main() {for (int i = 0; i < 4; ++i)cin >> b[i];// 生成一个全排列memset(selected, 0, sizeof selected);flag = false;for (int i = 0; i < 4; ++i) {if (selected[i])continue;selected[i] = 1;a[0] = b[i];for (int j = 0; j < 4; ++j) {if (selected[j])continue;selected[j] = 1;a[1] = b[j];for (int k = 0; k < 4; ++k) {if (selected[k])continue;selected[k] = 1;a[2] = b[k];for (int l = 0; l < 4; ++l) {if (selected[l])continue;selected[l] = 1;a[3] = b[l];calculate(4);if (flag)break;selected[l] = 0;}if (flag)break;selected[k] = 0;}if (flag)break;selected[j] = 0;}if (flag)break;selected[i] = 0;}if (!flag)cout << "NO" << endl;calculate(4);return 0;
}

OpenJudge 百练 2787 算24相关推荐

  1. 百练2787:算24题解

    2787:算24 查看 提交 统计 提示 提问 总时间限制:  3000ms  内存限制:  65536kB 描述 给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一 ...

  2. 58 - 算法 -分治问题 - 循环 二分查找 OpenJudge 百练 4143和为给定数

    #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cmath ...

  3. [OpenJudge] 百练2754 八皇后

    八皇后 Description 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. ...

  4. 贪心算法 openjudge 百练 python

    https://www.icourse163.org/learn/PKU-1001894005?tid=1450413466#/learn/content 程序设计与算法(二)算法基础 这里写目录标题 ...

  5. 【拓扑排序专题】Openjudge百练 4084 拓扑排序

    http://bailian.openjudge.cn/practice/4084/ 4084:拓扑排序 描述 给出一个图的结构,输出其拓扑排序序列,要求在同等条件下,编号小的顶点在前. 输入 若干行 ...

  6. 整数划分问题 递归 动态规划 openjudge 百练 python

    4117:简单的整数划分问题 http://bailian.openjudge.cn/practice/4117 4119:复杂的整数划分问题 http://bailian.openjudge.cn/ ...

  7. Python入门习题(63)——OpenJudge百练习题:DNA排序

    OpenJudge百练第1007号习题:DNA排序 题目描述 解题思路 参考答案 测试用例 小结 题目描述 来源 OpenJudge网站 – 百练习题集-第1007号习题 建议学编程的人士利用好这个网 ...

  8. 58 - 算法 - 百练 2503:Babelfish 二分查找与存储

    #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <cstdio> #include <cmath ...

  9. Bailian2787 算24【DFS】(POJ NOI0205-1789)

    问题链接:POJ NOI0205-1789 算24. 2787:算24 描述 给出4个小于10个正整数,你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式.现在的问题是,是否存在一种方 ...

  10. Python入门习题(82)——OpenJudge百练习题:第二大价值

    OpenJudge百练第4098号习题:第二大价值 题目描述 解题思路 参考答案 测试用例 小结 题目描述 来源 OpenJudge网站 -- 百练习题集-第4098号习题 要求 总时间限制: 300 ...

最新文章

  1. 语法错误 : 缺少“;”(在“类型”的前面)的解决方案 转载
  2. 聚焦2020年财报:进击的恒大汽车,“变态”的智能汽车
  3. python 常用内置函数_python常用内置函数使用|python基础教程|python入门|python教程...
  4. 广州种植牙需要多少钱
  5. 使有用计算机不注意卫生,保护眼睛注意细节有哪些
  6. onpagefinished等了很久才执行_今天自律了吗?停课不停锻炼 才是战疫正确姿势
  7. c语言逆波兰计算器程序,C语言实现的简单的逆波兰计算器
  8. 搬家请搬家公司好还是请朋友帮忙好?
  9. 「搬文工」Mac Finder 右键快速新建、复制、移动文件工具
  10. 分布式,项目发布管理
  11. python图像差分法目标检测_OpenCV实现帧差法检测运动目标
  12. windows10如何查看硬盘序列号
  13. 传奇服务器修改物品名字,幽冥传奇服务端目录说明及幽冥传奇开服修改文件目录...
  14. 转:量化投资新手指南-初识量化交易
  15. 微信小程序长列表优化方案
  16. C语言程序设计——结构体
  17. left join 和 left outer join (可解决多个表left join的问题)
  18. Excel使用攻略(1)
  19. VBA批量OCR识别提取身份证照片信息_白描网页版 - 高效准确且免费的OCR文字识别工具...
  20. 手机可以python编程吗_可以使用手机编程实现python吗

热门文章

  1. 怎么实现一个计算一年中有多少周?
  2. 郑州大学计算机考研拟录取名单,郑州大学2017年统考硕士生拟录取名单2(17)
  3. 市场爆发在即 分布式电站运维出路何在?
  4. SpringMVC使用Jedis发布后提示java.lang.ClassNotFoundException: redis.clients.jedis.Jedis问题
  5. 成百家之言,纳万端思辨,SDCC 2017·深圳站响号以待
  6. 样本量太小怎么做结构方程模型?
  7. 带上问题来看:主流技术Java、Python怎么?基本功又该怎么学?(什么是MySQL、Linux、算法?又该怎么用?)
  8. worldpress怎么增加登录注册按钮
  9. Linux程序包管理命令之rpm
  10. Python快速实现视频播放器