18.06.25 16年期末06 42点
描述
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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <string> 3 #include <memory.h> 4 #include <algorithm> 5 #include <stdlib.h> 6 #include <math.h> 7 #include <iostream> 8 #include<queue> 9 #include <set> 10 using namespace std; 11 12 set<int> dp[7][7]; 13 int num[7],n; 14 15 int main() 16 { 17 scanf("%d", &n); 18 for (int i = 1; i <= n; i++) 19 { 20 scanf("%d", &num[i]); 21 dp[i][i].insert(num[i]); 22 } 23 int sum = 1; 24 for (int i = 2; i <= n; i++) 25 sum += i; 26 for (int _case = 1; _case <= sum; _case++) { 27 next_permutation(num, num + n); 28 for(int i=2;i<=n;i++) 29 for (int j = 1; j <= n - i + 1; j++) { 30 for (int k = j; k <= j+i-2; k++) { 31 for(auto ii=dp[j][k].begin();ii!=dp[j][k].end();ii++) 32 for (auto jj = dp[k + 1][j + i - 1].begin(); jj != dp[k + 1][j + i - 1].end(); jj++) { 33 dp[j][j + i - 1].insert(*ii + *jj); 34 dp[j][j + i - 1].insert(abs(*ii - *jj)); 35 dp[j][j + i - 1].insert(*ii * *jj); 36 if (*jj != 0 && (*ii / (*jj)*(*jj)) == *ii) 37 dp[j][j + i - 1].insert(*ii / (*jj)); 38 } 39 } 40 } 41 } 42 if (dp[1][n].find(42) != dp[1][n].end()) 43 printf("YES\n"); 44 else 45 printf("NO\n"); 46 return 0; 47 }
一开始是想以先确定第一个相加的数逐层递归下去的方式做的
虽然没有用递归函数套函数的方法做但还是TLE
这个方法的话……我感觉我在考试的时候并不会想的起来还有全排列这种函数可以用
思路:
确定下式子中各个数的顺序,
然后可以相当简便地动规, dp[x][y] 是从第x个数到第y个数算出的所有可能解
不太常规的动规吧
注定失败的战争,也要拼尽全力去打赢它;
就算输,也要输得足够漂亮。