GOJ 1454 计算24点

来源:互联网 发布:windows快速打开程序 编辑:程序博客网 时间:2024/06/06 15:41

思路:算24点可以归结为 A B C D=24(中间添加运算符以及括号)。一共4个数,对其进行全排列4!=24种,然后对于每一种排列添加运算符和括号。判断结果是否等于24.

这种题目是思路很简单,但是实践起来却很考研编程技巧以及思维上的取巧。

首先要引入一个以前从未接触过的函数:next_permutation。(全排列函数,用之前一定要sort一下,因为它只输出当前这种排列后的排列)

范例:

第一个输出结果第一列都为1,下面分别是1 2 3中缺失的。具体可以百度一下。

然后就是小技巧了:对于+和*来说它们满足交换律,但对于-和/来说则不满足,因此,这里定义一个(~/)和(~-)的概念,这样就有a-b=b~-a,于是乎所有操作都满足交换律。即所有的括号添加就只有这两种情况:(((a#b)#c)#d)和(a#b)#(c#d)这里的"#"表示任意运算。其他的添加括号的方式都可以通过交换律转化成这两种。

具体参考:http://blog.csdn.net/octopusflying/article/details/51428337。

代码:

#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;int n,a[4];double eps=1e-6;///因为用到double所以注意精度的设置double cal(double a,double b,int op){///注意传值传double    if(op==0)        return (a+b)*1.0;    else if(op==1)        return (a-b)*1.0;    else if(op==2)        return (b-a)*1.0;    else if(op==3)        return a*b*1.0;    else if(op==4&&b!=0)        return (1.0*a)/b;    else if(op==5&&a!=0)        return (1.0*b)/a;}void solve(){    do{        for(int i=0;i<6;i++)            for(int j=0;j<6;j++)             for(int k=0;k<6;k++){             if(abs(cal(cal(cal(a[0],a[1],i),a[2],j),a[3],k)-24)<eps)///((a$b) $c)$d             {printf("YES\n");return;}             if(abs(cal(cal(a[0],a[1],i),cal(a[2],a[3],k),j)-24)<eps)///(a$b)$(c$d)             {printf("YES\n");return;}            }    }while(next_permutation(a,a+4));    printf("NO\n");    return;}int main(){    while(scanf("%d",&n)!=EOF){        for(int i=0;i<n;i++){            for(int j=0;j<4;j++)                scanf("%d",&a[j]);        sort(a,a+4);        solve();        }    }    return 0;}

原创粉丝点击