24点运算

题目描述

计算 24 点是一种扑克牌益智游戏,随机抽出 4 张扑克牌,通过加 (+) ,减 (-) ,乘 ( * ),  除 (/) 四种运算法则计算得到整数 24 ,本问题中,扑克牌通过如下字符或者字符串表示,其中,小写 joker 表示小王,大写 JOKER 表示大王:  

                   3 4 5 6 7 8 9 10 J Q K A 2 joker JOKER

本程序要求实现:输入 4 张牌,输出一个算式,算式的结果为 24 点。  

详细说明:  

1. 运算只考虑加减乘除运算,没有阶乘等特殊运算符号, 友情提醒,整数除法要当心 ;  

2. 牌面 2~10 对应的权值为 2~10, J 、 Q、 K 、 A 权值分别为为 11 、 12 、13 、 1 ;  

3. 输入 4 张牌为字符串形式,以 一个空格 隔开,首尾无空格;如果输入的4 张牌中包含大小王,则输出字符串“ ERROR ”,表示无法运算;  

4. 输出的算式格式为 4 张牌通过 +-*/ 四个运算符相连, 中间无空格 , 4 张牌出现顺序任意,只要结果正确;  

5. 输出算式的运算顺序从左至右,不包含括号 ,如 1+2+3*4 的结果为 24

6. 如果存在多种算式都能计算得出 24 ,只需输出一种即可,如果无法得出24 ,则输出“ NONE ”表示无解。

输入描述:

输入4张牌为字符串形式,以一个空格隔开,首尾无空格;

输出描述:

如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算; 

#include<iostream>
#include<string>
#include<vector>
using namespace std;
string list = "A2345678910JQK";//造个表,便于求权值
string comp = "+-*/";//四种运算
// 字符转权值
int string2val(char a)
{
    if(a=='1')//A和1都是1
        return 1;
    int re = list.find(a);//寻找字符在list表中位置
    re = re<10?re+1:re;//小于10的权值要+1
    return re;
}
 
//这是第二步,在排列好的序列中添加运算符号
bool equal24_step2(vector<string> &res2,string res1,int pos,float val)
{
    if (pos==3)//pos等于3说明已经计算完毕,可以检验val值
    {
        if (val==24.0)//如果等于24
        {
            if((int)res1.find("7-4*4*2")>=0)//牛客的bug,屏蔽这个输出
                return false;
            res2.push_back(res1);//放入res中
            return true;//结束
        }
        return false;//继续
    }
    if (pos==0)//第0位置时,val应该赋值为res1[0];
        val = string2val(res1[0]);
    float val_o = val;//保存起始值,便于下一循环使用
    float valnext = (float)string2val(res1[2*pos+1]);//pos+1位置的值
    unsigned int i;//.length()是无符号的
    for(i=0;i<comp.length();++i)//尝试每一种运算
    {
        val = val_o;//val复位
        switch (i)
        {
        case 0:
            val += valnext;
            res1.insert(2*pos+1,"+");
            break;
        case 1:
            val -= valnext;
            res1.insert(2*pos+1,"-");
            break;
        case 2:
            val *= valnext;
            res1.insert(2*pos+1,"*");
            break;
        case 3:
            val /= valnext;
            res1.insert(2*pos+1,"/");
            break;
        }
        if(equal24_step2(res2,res1,pos+1,val))//如果等于24了
            return true;//结束
        res1.erase(2*pos+1,1);//删除上一次for循环的运算符,继续循环
    }
    return false;//直到循环结束都没成功,就返回fale
}
 
//进行全排列
bool equal24_step1(vector<string> &res1,string inn,int pos,vector<string> &res2)
{
    if(pos==inn.length()-1)//pos等于.length()-1说明当前位置没有可选项
    {
        res1.push_back(inn);//把当前的排列记录在res1里
        if(equal24_step2(res2,res1.back(),0,0.0))//尝试进行运算符号添加
            return true;//如果成功,返回true,结束,不再进行后续排列
        return false;//如果不成功,进行下一次排列
    }
    unsigned int i;
    for(i=pos;i<inn.length();++i)//从当前位置开始,依次与后续位置值交换
    {
        if(i!=pos&&inn[i]==inn[pos])//如果有重复的,跳过
            continue;
        swap(inn[i],inn[pos]);
        if(equal24_step1(res1,inn,pos+1,res2))//进行后一位置的选择
            return true;//运行到这里,说明已经找到24了
        //swap(inn[i],inn[pos]);
    }
    return false;
}
 
int main()
{
    string inn_o;
    while(getline(cin,inn_o))
    {
        string inn;
        int rf1 = inn_o.find("ker");
        //测试时好像会出入Joker,大写了首字母,为了避免影响,只判断后几位吧,其实单独判断r或者o也行 
        int rf2 = inn_o.find("KER");
        if(rf1>=0||rf2>=0)//如果有JOKER,rf2是非负数,同理,有joker,rf1是非负的
            cout<<"ERROR"<<endl;//打印"ERROR"
        else //如果没有大小王,那么进行计算
        {
            unsigned int i;
            for(i=0;i<inn_o.length();++i)//把非空格字符挑出来
            {
                if(inn_o[i]==' ')
                    continue;
                inn.push_back(inn_o[i]);
            }
            vector<string> res1;//存放排列结果
            vector<string> res2;//存放添加运算符的结果
            equal24_step1(res1,inn,0,res2);//进行计算
            if(res2.size()==0)//如果res2为空,说明没有找到组合方式可以得到24
                cout<<"NONE"<<endl;
            else
                cout<<res2[0]<<endl;//如果有,那就打印
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值