您的位置:首页 > 其它

华为OJ题目:24点运算

2015-08-14 20:53 483 查看
计算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的结果为246.如果存在多种算式都能计算得出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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: