hihoCoder-24点

本文转载自hihoCoder 搜索一·24点
题意:24点是一个棋牌类益智游戏。拿一副牌,抽去大小王和JQK,剩下1到10这40张牌(以下用1代替A)。任意抽取4张牌,用加、减、乘、除(可加括号)把牌面上的数算成24。每张牌必须且只能用一次。如抽出的牌是3、8、8、9,那么算式为(9-8)×8×3=24。输入第1行是1个正整数t表示数据组数,2≤t≤100;第2..t+1行是4个正整数a,b,c,d,1≤a,b,c,d≤10。输出第1..t行每行一个字符串,第i行表示第i组能否计算出24点。若能够输出"Yes",否则输出"No"。
解析:
假设我们用⊙表示运算,⊙除了可以表示基本的"+","-","*","/"外,我们还引入两个新的运算,"反-",和"反/"。比如(a反/b)的意思是(b/a)。则对形如(c/(a+b))的形式,就可以等价的描述为((a+b)反/c)。利用这6种运算,可以将所有可能的计算过程归结为2类:(((a⊙b)⊙c)⊙d)和((a⊙b)⊙(c⊙d))。将4张牌的值,分别代入a,b,c,d,再把可能的运算符也代入就可以得到相应的计算式子,将其计算出来,再检查结果是否等于24。由于我们有4个数,所以对于a,b,c,d的对应关系有4!=24种情况。3个运算符,每个运算符可能有6种情况,那就是6^3=216。再考虑到2种不同的模式,所以一共有2*24*216=10368种情况。这并没有考虑等价的情况,比如a+b和b+a,所以实际的情况数其实是小于10368种的。不过由于对计算机而言,10368种情况数本来也不是很多,而要考虑等价反而显得比较麻烦。所以我们可以不要去考虑加法和乘法的可逆性,直接枚举所有的情况。
AC代码:

#include<cstdio>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
double a[4];  
bool flag;  

double cnt(double a,double b,int k)  
{  
    double s=0.0;  
    switch(k)  
    {  
        case 0:s=a+b;break;  
        case 1:s=a-b;break;  
        case 2:s=a*b;break;  
        case 3:if(b!=0)s=a/b;break;  
        case 4:s=b-a;break;  
        case 5:if(a!=0)s=b/a;break;  
    }  
    return s;  
}  

bool judge(int i,int j,int k)  
{  
    if(s(cnt(cnt(a[0],a[1],i),a[2],j),a[3],k)==24) return true;  
    if(cnt(cnt(a[0],a[1],i),cnt(a[2],a[3],k),j)==24) return true;  
    return false;  
}  

void solve()  
{  
	for(int i=0;i<6;i++)
	{ 
		for(int j=0;j<6;j++)
		{
            for(int k=0;k<6;k++)  
            {
                if(judge(i,j,k))  
                {  
                    flag=true;  
                    return;  
                }
            }
		}
	}
} 
 
int main()  
{  
    int N;  
    cin>>N;  
    while(N--)  
    {  
        flag=false;  
        for(int i=0;i<4;i++) cin>>a[i];  
        sort(a,a+4);  
        do  
        {  
            solve();  
            if(flag) break;  
        }  
        while(next_permutation(a,a+4));  
        if(flag)printf("Yes\n");  
        else printf("No\n");  
    }  
}


你可能感兴趣的:(hihoCoder-24点)