[CDOJ1252]-24点-模拟/搜索

来源:互联网 发布:手机网络无法登陆钉钉 编辑:程序博客网 时间:2024/06/02 03:25

说在前面

机房的大佬给我们找了一堆搜索题练习代码量,然后me挑了一道写…
然而这题一点都不考代码量,想一想怎么写比较简单,剩下的事情就是复制粘贴了=w=
(论如何在10分钟之内写完一道搜索题)


题目

CDOJ1252传送门

题面

24点就是给你一串数字,问你是否通过加减乘除括号构成24点。
沈爷觉得这个很好玩,就决定考考你,给你4个数,可以交换位置,可以用加减乘除和括号,是否能构成24点呢?
注意哦~这里的除法并不是整数除法,比如样例

输入及输出

输入:
第一行T,表示有多少组测试数据,1≤T≤50
接下来T行,每行4个正整数a1, a2, a3, a4,表示每个数都是多少,其中1≤ai≤13
输出:
对于每一次询问,如果能够凑成24点,输出yes,否则输出no

样例

输入:
2
3 3 8 8
1 1 1 1
输出:
yes
no


解法

题面说的什么交换顺序啊,括号啊什么的,其实就是随意顺序,不要想复杂啦。

然后呢,模拟(暴搜)的时候大概是这样的:
当me还没有进行运算的时候,me有四个数。
第一次运算,me就会从初始的四个数中选两个数出来进行运算,然后me还剩三个数
第二次运算,me就会从剩下的三个数里面选出两个数进行运算,然后me还剩两个数
第三次运算,me会将剩下的两个数进行运算,最后剩下一个数
第四次,me只需要检查当前剩下的数是否是24就可以了

然后写个dfs就可以水过,复杂度:( 6 * 6 ) * ( 3 * 6 ) * ( 2 * 6 ),每个括号表示一层,括号内第一个数字表示从剩下的数里选择两个数的方案数,第二个表示运算种数(减法和除法各有两种,因为有方向)

注意使用除法的时候记得判定除数不能为0,还有要注意eps


下面是自带大常数的代码

#include <cstdio>#include <cstring>#include <algorithm>using namespace std ;int T ;double num[5][5] , eps = 1e-8 ;int dcmp( double x ){    if( x > -eps && x < eps ) return 0 ;    return ( x > 0 ? 1 : -1 ) ;}bool dfs( int dep ){    //printf( "dep = %d : %f %f %f %f\n" , dep , num[dep][1] , num[dep][2] , num[dep][3] , num[dep][4] ) ; getchar() ;    if( dep == 4 ){        if( dcmp( num[dep][1] - 24.0 ) == 0 ) return true ;        return false ;    }    int topp = 0 ;    for( int i = 1 ; i < 4 - dep + 1 ; i ++ ){        for( int j = i + 1 ; j <= 4 - dep + 1 ; j ++ ){            //add            topp = 0 ;            for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;            num[dep+1][++topp] = num[dep][i] + num[dep][j] ;            if( dfs( dep + 1 ) ) return true ;            //minus i-j            topp = 0 ;            for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;            num[dep+1][++topp] = num[dep][i] - num[dep][j] ;            if( dfs( dep + 1 ) ) return true ;            //minus j-i            topp = 0 ;            for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;            num[dep+1][++topp] = num[dep][j] - num[dep][i] ;            if( dfs( dep + 1 ) ) return true ;            //multiply            topp = 0 ;            for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;            num[dep+1][++topp] = num[dep][i] * num[dep][j] ;            if( dfs( dep + 1 ) ) return true ;            //division i/j            if( dcmp( num[dep][j] ) != 0 ){                topp = 0 ;                for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                    if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;                num[dep+1][++topp] = num[dep][i] / num[dep][j] ;                if( dfs( dep + 1 ) ) return true ;            }            //division j/i            if( dcmp( num[dep][i] ) != 0 ){                topp = 0 ;                for( int k = 1 ; k <= 4 - dep + 1 ; k ++ )                    if( k != i && k != j ) num[dep+1][++topp] = num[dep][k] ;                num[dep+1][++topp] = num[dep][j] / num[dep][i] ;                if( dfs( dep + 1 ) ) return true ;            }        }    }    return false ;}int main(){    scanf( "%d" , &T ) ;    for( int i = 1 ; i <= T ; i ++ ){        for( int j = 1 ; j <= 4 ; j ++ )            scanf( "%lf" , &num[1][j] ) ;        puts( dfs( 1 ) ? "yes" : "no" ) ;    }}