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. Django实战(20):分页(Pagination)
  2. 【Prince2科普】衡量绩效的六大要素
  3. comparable和comparator比较
  4. C++通过hiredis连接到redis
  5. NMAP扫描技巧:TCP空闲扫描
  6. mybatis 用Log4j输出日志
  7. 使用MyEclipse将HTML5移动项目迁移到PhoneGap(一)
  8. latex图片标题居中
  9. 简单粗暴无需拼接下载 blob (ts)视频文件
  10. 如何为你的博客园添加到百度统计
  11. [转载] C#面向对象设计模式纵横谈——7. Adapter适配器模式
  12. ROS限速不生效问题
  13. 蓝桥杯 BASIC-26 基础练习 报时助手
  14. network of emergency contacts---BFS
  15. 把C++语言的书读薄
  16. IDEA 常用快捷键 常用插件 2
  17. 扫码连wifi小程序源码
  18. 苹果macOS 13 Ventura 5K原生动态壁纸
  19. 认清有毒的矿物质元素 预防中毒
  20. 计算机电脑故障,电脑常见故障解决方法

热门文章

  1. kali linux软件源更新,系统美化
  2. 计算机防勒索病毒需求分析
  3. 一个简单的库存控制模型
  4. UniAPP 使用高德地图,打包后定位api不执行
  5. 腾讯视频一二三面和携程后台开发一面二面面经
  6. 搭建企业级数据治理体系指南
  7. kotlin Android通过GPS定位/网络定位获取当前经纬度及位置信息
  8. [操作系统]进程同步 Reader-Writer问题 共享缓冲区问题 面包师问题 吸烟者问题
  9. 智能剪刀——交互式图像分割
  10. magento-onestep-checkout-remove-payment-method-step