业余爱好(24点问题)

2020-09-27  本文已影响0人  这样你就找不到我了

四个数的运算结果,可以看成三个数的运算结果与一个数的运算结果
三个数的运算结果,可以看成两个数的运算结果与一个数的运算结果
两个数的运算结果,可以看成一个数的运算结果与一个数的运算结果

我们A,B,B,D表示四个数,用X表示某种运算关系,可以得到如下:

X(ABCD)= X(A X(BCD))
X(A X(BCD)) = X(A X(X(B X(CD))))
X(A X(X(B X(CD))))= X(A X(X(B X(X(CXD)))))

以上可知:任意四个数的运算结果,可以转化为前两个数的运算结果 与 第三个数的运算结果 与 第四个数的运算结果。

值得注意的是,如果是1 2 3 4 这四个数,其实同时包含了 -1 -2 -3 -4 这四个数。

举个例子:
5x(5-1/5)= -1/5的结果 + 5 的结果 x 5的结果 = (-1/5+5)x5

因此我们可以设计程序,从左至右,每次计算两个枚举数的值,进而得出最终结果。

这里使用深度遍历的方式枚举所有的可能,ABCD四个数,在1234个位置上都要出现
dfs(int n,double ans int *a)的n表示当前结算第几个数与ans的运算结果,ans记录上一次运算的结果,数组a中存储着ABCD四个数。
最开始,我们默认第一个计算的结果ans为数组中的第一个数,即ans = a[0],注意这里的a[0]每次计算之后需要调整,使ABCD四个数都在a[0]中出现过。
0位置的数用完之后,与之计算的下一个数自然就是1位置的数了,所以n初值为1。
使用0123这四个数映射+-x/四种运算。
注意前面提到的,每个数都可以变为负数。

#include<stdio.h>


int flag = 0;
void dfs(int n,double ans,int *a){
    if(n==4){
        if(ans == 24){
            flag = 1;//flag=1输出Yes 
        }
    }
    if(n<4){
    for(int i=n;i<4;i++)
        for(int w=0;w<4;w++){
            if(w==0){
                dfs(n+1,ans+a[n],a);
                dfs(n+1,-(ans+a[n]),a);
            }
                
            if(w==1){
                dfs(n+1,ans-a[n],a);
                dfs(n+1,-(ans-a[n]),a);
            }
            
            if(w==2){
                dfs(n+1,ans*a[n],a);
                dfs(n+1,-ans*a[n],a);
            }
            
            if(w==3){
                dfs(n+1,ans/double(a[n]),a);
                dfs(n+1,-ans/double(a[n]),a);
            }
        }
    }
}

int main(){
    int point[2];
    while(true){
        int a[4];
        for(int i=0;i<4;i++){
            scanf("%d",a+i);
        }
        if(a[0]==0&&a[1]==0&&a[2]==0&&a[3]==0)
            break;
        
        for(int i=0;i<4;i++){
            //四个数都有机会充当第一个数进行计算
            int t = a[0];
            a[0] = a[i];
            a[i] = t;
            dfs(1,a[0],a);
            //别忘了还原,下次还要交换 
            t = a[0];
            a[0] = a[i];
            a[i] = t;
        }
            
        
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
        flag = 0;
        
    }
    return 0;
} 



上一篇 下一篇

猜你喜欢

热点阅读