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