首页 > 其他 > 详细

11F:42点

时间:2020-06-16 22:11:41      阅读:67      评论:0      收藏:0      [点我收藏+]
总时间限制: 
1000ms
 
内存限制: 
65536kB
描述

42是:

·组合数学上的第5个卡特兰数

·字符‘*‘的ASCII码

·钼的原子序数

·6与9的乘积结果的13进制表示

·生命、宇宙以及任何事情的终极答案

·以及……表达式(1+5)/2*(6-4)*7的值

因此,小机器人Marvin发明了这个叫42点的小游戏。在这个游戏中,玩家会获得n个数。玩家需要使用‘+‘、‘-‘、‘*‘、‘/‘、‘(‘、‘)‘以及这n个数构成一个合法的中缀表达式,并使得该表达式的值为42。n个数之间的顺序可以改变。表达式运算过程中只能出现整数。

由于过于抑郁,Marvin无力完成这个游戏,于是来找你帮忙。你的任务是对于给定的n个数,判断他们是否能根据上述游戏规则算出42。

输入
第一行为一个数n,1<=n<=6。
第二行为n个数,每个数均为[1,13]范围内的整数。
输出
输出一行,若可以算出42则输出“YES”,否则输出“NO”(注意大小写)。
样例输入
6
1 5 2 6 4 7
样例输出
YES

代码:

 1 #include <iostream>
 2 #include <vector>
 3 #include <cmath>
 4 #include <algorithm>
 5 using namespace std;
 6 vector<int> ele;
 7 int n;
 8 
 9 bool dfs(int m){
10     if(m == 1){
11         if(ele[0] == 42)
12             return true;
13         return false;
14     }
15     for(int i = 0; i < m - 1; ++i)
16         for(int j = i + 1; j < m; ++j){
17             int t1 = ele[i], t2 = ele[j];
18             ele[i] = t1 + t2;
19             ele[j] = ele[m - 1];
20             if(dfs(m - 1))
21                 return true;
22             ele[i] = t1 - t2;
23             if(dfs(m - 1))
24                 return true;
25             ele[i] = t2 - t1;
26             if(dfs(m - 1))
27                 return true;
28             ele[i] = t1 * t2;
29             if(dfs(m - 1))
30                 return true;
31             if(t2 != 0 && abs(t1) % abs(t2) == 0){
32                 ele[i] = t1 / t2;
33                 if(dfs(m - 1))
34                     return true;
35             }
36             else if(t1 != 0 && abs(t2) % abs(t1) == 0){
37                 ele[i] = t2 / t1;
38                 if(dfs(m - 1))
39                     return true;
40             }
41             ele[i] = t1, ele[j] = t2;
42         }
43     return false;
44 }
45 
46 int main(){
47     cin >> n;
48     int t;
49     for(int i = 0; i < n; ++i){
50         cin >> t;
51         ele.push_back(t);
52     }
53   //  sort(ele.begin(), ele.end());
54     if(dfs(n))
55         cout << "YES" << endl;
56     else
57         cout << "NO" << endl;
58 }

备注:我坦白!这是上机练习的参考答案不是我写的代码。

感觉看这道题的答案获得了很多启发。其实没有技巧,不用动归,搜索就可以。排序是没用的,所以那行我给注释掉了。

数字的顺序是任意的,怎么体现呢?就是dfs里的两个循环,相当于每一次是随意从数列中挑两个数摘出来进行+-*\的运算。枚举的时候没考虑对称的情况,所以对于不对称运算减和除就两种都dfs一下就好了!我最开始没看懂的是,从数列中挑出两个数,运算完了之后把结果填进了ele[i],那ele[j]为啥填了个ele[m-1]?

技术分享图片

 

 其实就是因为两个数相加产生了一个空当,就非常巧妙的把最后一个数移到前面这个空当里,当然也可以把后面的所有数字整体往前移一位(which是时间上更复杂的,并且没有必要,因为数字的顺序是任意的),相当于就是缩短了序列,把ele[j]删掉了。i每次循环到最后一个数是m-1,所以这个序列就是越来越短的!我觉得还挺巧妙的qwq

11F:42点

原文:https://www.cnblogs.com/fangziyuan/p/13145108.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!