描述
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 <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个数算出的所有可能解
不太常规的动规吧
来源:oschina
链接:https://my.oschina.net/u/4274876/blog/3926873