《编程之美》1.16节《24点游戏》,这个不多说了,大家从小玩到大的。书中解法一用了枚举的方法,依次求解出所有7680种表达式的值;解法二用了分治的思想来优化算法,我写的算法就是根据解法二来的,书中的伪代码只能判断N个数能否求出24,而我改进之后就可以输出满足题意的表达式了。
算法中我用到C++ STL中的set容器,因为set中的元素都是非重的。
//实现N个数通过简单的运算得到结果24.
CODE
//24Game
//2010-01-17
//by roovent
#include <iostream>
#include <sstream>
#include <string>
#include <set>
#define N 4
#define M (1<<N)
#define TARGET 24
using namespace std;
struct Element
{
double num;
string expression;
friend bool operator< (const Element& a, const Element& b)
{
return a.num < b.num;
}
};
//--全局变量
set<Element> result[M];
//--全局变量结束
set<Element> Process(const int x, int* nums)
{
set<Element> s;
for(int i = 1; i < x; ++i)
{
if((i|x) == x && x-i>i) //i是x的子集,x-i是其补集,确保子集与其补集不重复运算
{
for(set<Element>::iterator p = result[i].begin(); p != result[i].end(); ++p)
{
for(set<Element>::iterator q = result[x-i].begin(); q != result[x-i].end(); ++q)
{
Element e;
double dbA = (*p).num;
double dbB = (*q).num;
string strA = (*p).expression;
string strB = (*q).expression;
e.num = dbA + dbB;
e.expression = "(" + strA + " + " + strB + ")";
s.insert(e);
e.num = dbA - dbB;
e.expression = "(" + strA + " - " + strB + ")";
s.insert(e);
e.num = dbB - dbA;
e.expression = "(" + strB + " - " + strA + ")";
s.insert(e);
e.num = dbA * dbB;
e.expression = "(" + strA + " * " + strB + ")";
s.insert(e);
if(dbB != 0)
{
e.num = dbA / dbB;
e.expression = "(" + strA + " / " + strB + ")";
s.insert(e);
}
if(dbA != 0)
{
e.num = dbB / dbA;
e.expression = "(" + strB + " / " + strA + ")";
s.insert(e);
}
}
}
}
}
return s;
}
bool Solve(int* nums)
{
for(int i = 0; i < M; ++i)
{
result[i].clear();
}
for(int i = 0; i < N; ++i)
{
stringstream ss;
ss<<nums[i]; //将整型转化为字符串
Element e = {nums[i], ss.str()};
result[1<<i].insert(e);
}
for(int i = 1; i < M; ++i)
{
if(result[i].empty())
result[i] = Process(i, nums);
}
Element e = {TARGET, ""};
return result[M-1].find(e) != result[M-1].end();
}
int main()
{
int nums[N] =
{5,5,5,1};
//{3,3,7,7};
//{3,3,8,8};
//{1,4,5,6};
//{3,8,8,10};
//{4,4,10,10};
//{9,9,6,2};
cout<<"Problem: ";
for(int i = 0; i < N - 1; ++i)
{
cout<<nums[i]<<", ";
}
cout<<nums[N-1]<<endl;
if(Solve(nums))
{
Element e = {TARGET, ""};
cout<<"Solution: "<<(*(result[M-1].find(e))).expression << endl;
}
else
{
cout<<"No Solution"<<endl;
}
return 0;
}