华为OJ题目:24点运算

来源:互联网 发布:淘宝店铺怎么设置打折 编辑:程序博客网 时间:2024/05/26 02:20

计算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, JQKA权值分别为为1112131 
3.输入4张牌为字符串形式,以一个空格隔开,首尾无空格;如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算; 
4.输出的算式格式为4张牌通过+-*/四个运算符相连,中间无空格4张牌出现顺序任意,只要结果正确; 
5.输出算式的运算顺序从左至右,不包含括号,如1+2+3*4的结果为24
6.如果存在多种算式都能计算得出24,只需输出一种即可,如果无法得出24,则输出“NONE”表示无解。

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

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

只要结果正确; 

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

如果存在多种算式都能计算得出24,只需输出一种即可,如果无法得出24

则输出“NONE”表示无解。


解题思路:1,对输入的字符解析成int存储到raw[4]中。

2,对raw[]中的四个元素进行全排列(用迭代的方法)。

3,三次for循环计算四个元素进行运算后的结果。


看代码:


#include <iostream>using namespace std;void permStr(char *str,int i);char allSor[24][5];char changeToOp(int r);static int k=0;int main(int argc, const char * argv[]) {    int i=0;        char raw[5];    raw[4]='\0';//后面用到strlen()时,标志元素结束
    while (i<4) {        cin>>raw[i];        if ((raw[i]>='2'&&(int)raw[i]<='1'+9)) {            i++;        }else if (raw[i]=='A'){            raw[i]='1';            i++;        }else if(raw[i]=='J'){            raw[i]='1'+10;            i++;        }else if(raw[i]=='Q'){            raw[i]='1'+11;            i++;        }else if(raw[i]=='K'){            raw[i]='1'+12;            i++;        }else{            cout<<"ERROR"<<endl;            return 0;        }    }//    cout<<strlen(raw)<<endl;        permStr(raw,0);        double ripe[24][4];        for (int i=0; i<24; i++) {            ripe[i][0]=allSor[i][0]-'0';            ripe[i][1]=allSor[i][1]-'0';            ripe[i][2]=allSor[i][2]-'0';            ripe[i][3]=allSor[i][3]-'0';        }                int ret=0;        for (int i=0; i<24; i++) {            for (int a=0; a<3; a++) {                for (int b=0; b<3; b++) {                    for (int c=0; c<3; c++) {                        switch (a) {                            case 0:                                ret=ripe[i][0]+ripe[i][1];                                break;                            case 1:                                ret=ripe[i][0]-ripe[i][1];                                break;                            case 2:                                ret=ripe[i][0]*ripe[i][1];                                break;                            case 3:                                ret=ripe[i][0]/ripe[i][1];                                break;                            default:                                break;                                                        }                        switch (b) {                            case 0:                                ret+=ripe[i][2];                                break;                            case 1:                                ret-=ripe[i][2];                                break;                            case 2:                                ret*=ripe[i][2];                                break;                            case 3:                                ret/=ripe[i][2];                                break;                            default:                                break;                        }                                                switch (c) {                            case 0:                                ret+=ripe[i][3];                                break;                            case 1:                                ret-=ripe[i][3];                                break;                            case 2:                                ret*=ripe[i][3];                                break;                            case 3:                                ret/=ripe[i][3];                                break;                            default:                                break;                        }                        if (ret==24) {                            cout<<ripe[i][0]<<changeToOp(a)<<ripe[i][1]<<changeToOp(b)<<ripe[i][2]<<changeToOp(c)<<ripe[i][3]<<endl;                            return 0;                        }                    }                }            }        }    cout<<"NONE"<<endl;    return 0;}char changeToOp(int r){    char op;    switch (r) {        case 0:            op='+'; break;        case 1:            op='-'; break;        case 2:            op='*'; break;        case 3:            op='/';            break;                    default:            break;    }    return op;}void swap(char *str1,char *str2){    char temp;    temp=*str1;    *str1=*str2;    *str2=temp;}void permStr(char *str,int i){//    printf("%d\n",i);//    cout<<strlen(str)<<endl;    if(i==strlen(str)-1){        allSor[k][0]=str[0];        allSor[k][1]=str[1];        allSor[k][2]=str[2];        allSor[k][3]=str[3];        allSor[k][4]='\0';        k++;//        printf("%s\n",str);//        cout<<allSor[k]<<endl;    }    else    {        for(int j=i;j<strlen(str);j++)        {//            printf("i %d,j %d\n",i,j);            swap(&str[i],&str[j]);            permStr(str,i+1);            swap(&str[i],&str[j]);        }    }}


提交后看到别人的代码如下:

#include <iostream>#include <string>#include <algorithm>using namespace std;string poker[] = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };char C[12] = { '+', '+', '+', '-', '-', '-', '*', '*', '*', '/', '/', '/' };int Calculate(int a, int b, char c){    switch (c){        case '+': return a + b;        case '-': return a - b;        case '*': return a * b;        case '/': return a / b;        default: return -1;  //不会有这个选项    }}int Caculate24(int a, int b, int c, int d, char C1, char C2, char C3){    return Calculate(Calculate(Calculate(a, b, C1), c, C2), d, C3);}bool Count24(int a, int b, int c, int d){    sort(C, C + 12);        do {        if (Caculate24(a, b, c, d, C[0], C[1], C[2]) == 24){            //do right;                        return true;        }    } while (next_permutation(C, C + 12));        return false;}int main(){    string str[4];    cin >> str[0] >> str[1] >> str[2] >> str[3];    int i, j;    bool legal;    for (i = 0; i < 4; i++){        legal = false;        for (j = 0; j < 13; j++){            if (str[i].compare(poker[j].c_str()) == 0)                legal = true;        }        if (legal == false){            cout << "ERROR" << endl;            return 0;        }    }        int a, b, c, d;    string *p;    p = find(poker, poker + 13, str[0]);    a = p - poker + 1;    p = find(poker, poker + 13, str[1]);    b = p - poker + 1;    p = find(poker, poker + 13, str[2]);    c = p - poker + 1;    p = find(poker, poker + 13, str[3]);    d = p - poker + 1;        //现在a, b, c, d分别代表每一张牌的数值    int num[4];    num[0] = a, num[1] = b, num[2] = c, num[3] = d;        do {        if (Count24(num[0], num[1], num[2], num[3])){            cout << poker[num[0] - 1] << C[0] << poker[num[1] - 1] << C[1] << poker[num[2] - 1] << C[2] << poker[num[3] - 1] << endl;            return 0;        }    } while (next_permutation(num, num+4));    cout << "NONE" << endl;    return 0;}


对比上述代码:第二种使用了许多STL中的函数。对标准库函数的掌握不


遇到的问题:

1,读入输入字符时没有设置结束标志位,导致后面调用全排列函数时返回的strlen(str)值为10(实际应为4)。

strlen的结果要在运行的时候才能计算出来,主要用来计算字符串的长度,不是类型占内存的大小,strlen只能用char*做参数,且必须是以''\0''结尾的。
2,cin的用法:cin空字符(包括回车,TAB,空格)都会当成一个输入的结束。连续的空字符会被忽略。
阅读第二种实现代码学到的知识:
1,使用STL的next_permutation函数生成全排列(C++)首先要先对要进行全排列的数据进行生序排列;因为该函数返回一个bool值,原来他是按照增序对参数的每一个值进行排列的,如果参数为完全降序的话,就认为到头了,会返回false。
http://www.slyar.com/blog/stl_next_permutation.html
http://blog.csdn.net/hongchangfirst/article/details/8663899



0 0
原创粉丝点击