计算24点很简单的小程序,这一段用于解决不改变顺序的24点计算。不过最后总是有一些冗余的括号,这里为了通过SB的POJ3983,只写了一个去除最外层括号的函数,因为对这类问题的完善不太热心,就不关心去括号的事了
编译环境:G++4.6 under Fedora
/**
This piece is used to solve the POJ3983.It's another 24-point game.
The code piece is oriented from the Beauty of Programming, yet with adjustment
to solve 3983 and to make it more like C++ style.Optimization still needed.
Bug Log: Declared LIMEN as int, and equal() never returned true.
**/
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <assert.h>
using namespace std;
//Judge whether two double value is equal
bool equal(double,double);
//Try an operator and deal with num array and expressions
inline bool tryExp(double *num,string *exp,
const double &a,const double &b,
const string &expA,const string &expB,
int i,int n,char opt);
//Recursive body of the solution,return true and stop if solution found
bool findExp(double *,string*,int);
//Test functions
void
printExp(string *exp,int n) {
for(int i=0;i<n;i++)
cout<<exp[i]<<endl;
}
//Judge whether two double value is equal
bool
equal(double a,double b) {
const double LIMEN=0.0001;
return fabs(a-b)<LIMEN;
}
inline bool
tryExp(double *num,string *exp,
const double &a,const double &b,
const string &expA,const string &expB,
int i,int n,char opt) {
switch(opt) {
case '+':num[i]=a+b;break;
case '-': num[i]=a-b;break;
case '*':num[i]=1.0*a*b;break;
case '/':num[i]=1.0*a/b;break;
}
exp[i]='('+expA+opt+expB+')';
return findExp(num,exp,n-1);
}
bool
findExp(double *num,string *exp, int n) {
assert(n<=4);
assert(n>0);
if(n==1) {
if(equal(num[0],24))
return true;
else
return false;
}
for(int i=0;i<n-1;i++) {
double a=num[i];
double b=num[i+1];
string expA=exp[i];
string expB=exp[i+1];
//Adjust the remain elements
for(int j=i+1;j<n-1;j++) {
exp[j]=exp[j+1];
num[j]=num[j+1];
}
if(tryExp(num,exp,a,b,expA,expB,i,n,'+'))
return true;
if(tryExp(num,exp,a,b,expA,expB,i,n,'-'))
return true;
if(tryExp(num,exp,a,b,expA,expB,i,n,'*'))
return true;
if(!equal(b,0) && tryExp(num,exp,a,b,expA,expB,i,n,'/'))
return true;
//Adjust the array again and make process above never happened^_^
for(int j=n-1;j>i;j--) {
num[j]=num[j-1];
exp[j]=exp[j-1];
}
num[i]=a;
num[i+1]=b;
exp[i]=expA;
exp[i+1]=expB;
}
return false;
}
#include <cstring>
void removeOutsideBrackets(string &exp){
char s[50];
strcpy(s,exp.c_str());
int len=strlen(s);
if(s[0]=='(' && s[len-1]==')')
strncpy(s,s+1,len-1);
s[len-2]=0;
exp=s;
}
int main()
{
double num[4];
string exp[4];
//Input the initial numbers. As we need expression form,
//here input string and transform that to number later
//will hit two birds with one stone.
for(int i=0;i<4;i++) {
cin>>exp[i];
num[i]=atoi(exp[i].c_str());
}
if(findExp(num,exp,4)) {
removeOutsideBrackets(exp[0]);
cout<<exp[0]<<endl;
}
return 0;
}