- 总时间限制:
- 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