题目:点击打开链接
这个题写了我好久好久………………样例一直都过不了= =。
24点游戏,给你几个数,看能不能构成24点。
刚看到题,想的就是对数字进行全排列然后再对符号进行全排列,还要特殊处理括号,相当麻烦.
其实这个题用不着全排列所有数字,只要每次在数组中选取两个之前没有运算过的数字进行运算,其中运算包括6种:加,减, 乘,除,被减,被除,将结果存入数组,为避免重复使用数字,要标记那两个数已经用过。m个数经过m - 1次运算就可以得到最后的结果,将最后的结果跟24进行比较,比较的时候要注意精度问题。因为随机的取数进行运算并且运算除了加,减, 乘,除,还有被减,被除,这样就可以枚举所有的组合情况,就不用进行全排列了,感觉还是挺有收获的……
#include <stdio.h>
#include <string.h>
#include <math.h>
int n;
double sum, a[10];
bool vis[10];
int dfs(int m, int top)
{//m记录运算了几次,top是下一次运算的结果存放的位置
if(m == 1)
{
if(fabs(sum - a[top - 1]) < 0.000001)
return 1;
else
return 0;
}
int i, j;
for(i = 0; i < top - 1; i++)
{
if(!vis[i])
{//i位置的数没有使用过
vis[i] = 1;
for(j = i + 1; j < top; j ++)
{
if(!vis[j])
{
vis[j] = 1;
a[top] = a[i] + a[j];
if(dfs(m - 1, top + 1))
return 1;
a[top] = a[i] - a[j];
if(dfs(m - 1, top + 1))
return 1;
a[top] = a[j] - a[i];
if(dfs(m - 1, top + 1))
return 1;
a[top] = a[i] * a[j];
if(dfs(m - 1, top + 1))
return 1;
if(a[i] != 0)
{
a[top] = a[j] / a[i];
if(dfs(m - 1, top + 1))
return 1;
}
if(a[j] != 0)
{
a[top] = a[i] / a[j];
if(dfs(m - 1, top + 1))
return 1;
}
vis[j] = 0;//注意位置…………
}
}
vis[i] = 0;//注意………
}
}
return 0;
}
int main (void)
{
int t;
scanf("%d", &t);
while(t --)
{
memset(vis, 0, sizeof(vis));
scanf("%d", &n);
scanf("%lf", &sum);
int i;
for(i = 0; i < n; i++)
scanf("%lf", &a[i]);
if(dfs(n, n))
printf("Yes\n");
else
printf("No\n");
}
return 0;
}