zoukankan      html  css  js  c++  java
  • 24点游戏

    2017-08-05  22:44:37

    一、判断是否有解

    问题描述:

    问题求解:

        public boolean judgePoint24(int[] nums) {
            double[] nums_ = new double[4];
            for (int i = 0; i < 4; i++) nums_[i] = nums[i] * 1.0;
            return helper(nums_, 4);
        }
    
        private boolean helper(double[] nums, int n) {
            if (n == 1) return Math.abs(nums[0] - 24) < 0.001;
            double[] nums_ = Arrays.copyOf(nums, n);
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    double[] res = calc(nums[i], nums[j]);
                    for (double k : res) {
                        nums_[i] = k;
                        nums_[j] = nums[n - 1];
                        if (helper(nums_, n - 1)) return true;
                        nums_[j] = nums[j];
                        nums_[i] = nums[i];
                    }
                }
            }
            return false;
        }
    
        private double[] calc(double i, double j) {
            return new double[]{i + j, i - j, j - i, j * i, i / j, j / i};
        }
    

    二、打印所有解

    24点的计算问题我从小就在玩,而且还玩的不错。不过学习编程之后呢,一直没有系统的解决过这个问题。之前做华为的编程测试题的时候有一条算24的题,是采用的暴力枚举的方式进行的。这次采用了递归的方法进行计算。算法思想如下:

    • n个数算24,必有两个数要先算。这两个数算的结果,和剩余n-2个数,就构成了n-1个数求24的问题
    • 枚举先算的两个数,以及这两个数的运算方式。
    • 边界条件:一个数算24
    • 注意:浮点数比较是否相等,不能用 ==
    double a[5];
    #define EPS 1e-6
    
    vector<double> vec;
    string str;
    
    bool isZero(double x) {
    return fabs(x) <= EPS;
    }
    
    string d2s(double in)
    {
        stringstream s;
        string rst;
        s<<in;
        s>>rst;
        return rst;
    }
    
    bool count24(double a[],int n)
    {// 用数组a 里的 n 个数,计算24
        if( n == 1 ) {
            if(isZero( a[0] - 24) )
            {
                for(int i=0;i<vec.size();++i) cout<<vec[i]<<" ";
                cout<<endl;
                cout<<str<<endl;
                return true;
            }
            else
                return false;
        }
    
        double b[5];
    
        for(int i = 0;i < n-1; ++i)
            for(int j = i+1;j < n; ++j) { // 枚举两个数的组合
                int m = 0; // 还剩下m 个数, m = n - 2
                for(int k = 0; k < n; ++k)
                    if( k != i && k!= j)
                        b[m++] = a[k];// 把其余数放入b
                vec.push_back(a[i]);
                vec.push_back(a[j]);
                b[m] = a[i]+a[j];
                str.append("+");
                if(count24(b,m+1))
                    return true; 
                str.pop_back();
                str.append("-");
                b[m] = a[i]-a[j];
                if(count24(b,m+1))
                    return true;
                b[m] = a[j]-a[i];
                if(count24(b,m+1))
                    return true;
                str.pop_back();
                b[m] = a[i]*a[j];
                str.append("*");
                if(count24(b,m+1))
                    return true;
                str.pop_back();
                if( !isZero(a[j])) {
                    b[m] = a[i]/a[j];
                    str.append("/");
                    if(count24(b,m+1))
                        return true;
                    str.pop_back();
                }
                if( !isZero(a[i])) {
                    str.append("/");
                    b[m] = a[j]/a[i];
                    if(count24(b,m+1))
                        return true;
                    str.pop_back();
                }
                vec.pop_back();
                vec.pop_back();
            }
        return false;
    }
    string print(int i,int j,double ans=24)
    {
        if(i<0||j<0) return d2s(vec[1]);
        if(str[j]=='+') return d2s(vec[i])+"+("+print(i-2,j-1,vec[i+1])+")";
        if(str[j]=='*') return d2s(vec[i])+"*("+print(i-2,j-1,vec[i+1])+")";
        if(str[j]=='-')
        {
            if(abs((vec[i]-vec[i+1]-ans))<=EPS) return d2s(vec[i])+"-("+print(i-2,j-1,vec[i+1])+")";
            else return "("+print(i-2,j-1,vec[i+1])+")-"+d2s(vec[i]);
        }
        if(str[j]=='/')
        {
            if(abs((vec[i]/vec[i+1]-ans))<=EPS) return d2s(vec[i])+"/("+print(i-2,j-1,vec[i+1])+")";
            else return "("+print(i-2,j-1,vec[i+1])+")/"+d2s(vec[i]);
        }
    }
    int main() { for(int i = 0;i < 4; ++i) cin >> a[i]; if( count24(a,4)) { cout << "YES" << endl; cout<<print(4,2,24)<<endl; } else cout << "NO" << endl; return 0; }

    如果需要输出所有的解:

    double a[5];
    #define EPS 1e-6
    
    vector<double> vec;
    string str;
    
    bool isZero(double x) {
        return fabs(x) <= EPS;
    }
    
    string d2s(double in)
    {
        stringstream s;
        string rst;
        s<<in;
        s>>rst;
        return rst;
    }
    
    string print(int i,int j,double ans=24)
    {
        if(i<0||j<0) return d2s(vec[1]);
        if(str[j]=='+') return d2s(vec[i])+"+("+print(i-2,j-1,vec[i+1])+")";
        if(str[j]=='*') return d2s(vec[i])+"*("+print(i-2,j-1,vec[i+1])+")";
        if(str[j]=='-') 
        {
            if(abs((vec[i]-vec[i+1]-ans))<=EPS) return d2s(vec[i])+"-("+print(i-2,j-1,vec[i+1])+")";
            else return "("+print(i-2,j-1,vec[i+1])+")-"+d2s(vec[i]);
        }
        if(str[j]=='/') 
        {
            if(abs((vec[i]/vec[i+1]-ans))<=EPS) return d2s(vec[i])+"/("+print(i-2,j-1,vec[i+1])+")";
            else return "("+print(i-2,j-1,vec[i+1])+")/"+d2s(vec[i]);
        }
    }
    
    void count24(double a[],int n)
    {// 用数组a 里的 n 个数,计算24
        if( n == 1 ) {
            if(isZero( a[0] - 24) )
            {
                for(int i=0;i<vec.size();++i) cout<<vec[i]<<" ";
                cout<<endl;
                cout<<print(4,2,24)<<endl;
            }
        }
    
        double b[5];
    
        for(int i = 0;i < n-1; ++i)
            for(int j = i+1;j < n; ++j) { // 枚举两个数的组合
                int m = 0; // 还剩下m 个数, m = n - 2
                for(int k = 0; k < n; ++k)
                    if( k != i && k!= j)
                        b[m++] = a[k];// 把其余数放入b
                vec.push_back(a[i]);
                vec.push_back(a[j]);
    
                b[m] = a[i]+a[j];
                str.append("+");
                count24(b,m+1);
                str.pop_back();
    
                str.append("-");
                b[m] = a[i]-a[j];
                count24(b,m+1);
                str.pop_back();
    
                str.append("-");
                b[m] = a[j]-a[i];
                count24(b,m+1);
                str.pop_back();
    
                str.append("*");
                b[m] = a[i]*a[j];
                count24(b,m+1);
                str.pop_back();
    
                if( !isZero(a[j])) {
                    b[m] = a[i]/a[j];
                    str.append("/");
                    count24(b,m+1);
                    str.pop_back();
                }
                if( !isZero(a[i])) {
                    str.append("/");
                    b[m] = a[j]/a[i];
                    count24(b,m+1);
                    str.pop_back();
                }
                vec.pop_back();
                vec.pop_back();
            }
    }
    
    
    
    int main()
    {
        for(int i = 0;i < 4; ++i)
            cin >> a[i];
        count24(a,4);
        return 0;
    }
  • 相关阅读:
    在二进制与文本之间转换plist文件
    iOS 音频分贝的计算
    iOS 圆形水波浪效果实现
    iOS画圆、画线
    iOS IM开发准备工作(四)CocoaAsyncSocket的使用
    iOS IM开发准备工作(三)乱说Socket
    iOS IM开发准备工作(二)protobuf-objc安装及使用
    iOS IM开发准备工作(一)XML解析
    iOS IM开发blog写作计划
    西游记倒着看。。我从贴吧看来的
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/7292126.html
Copyright © 2011-2022 走看看