码迷,mamicode.com
首页 > 编程语言 > 详细

24点算法

时间:2015-05-13 14:55:46      阅读:167      评论:0      收藏:0      [点我收藏+]

标签:

24点游戏的算法,其中最主要的思想就是穷举法。所谓穷举法就是列出4个数字加减乘除的各种可能性,包括括号的算法。我们可以将表达式分成以下几种:首先我们将4个数设为a,b,c,d,,其中算术符号有+,-,*,/,。其中有效的表达式有a,ab-cd,等等。列出所有有效的表达式。其中我们用枚举类型将符号定义成数字常量,比如用1表示+,2表示-等。如下是我对穷举法的一种编程语言。在编程的头部要对变量做下定义。其中a,b,c,d的范围是1到10。这就需要在定义变量的时候要有限制。在vc++中的编程中,在定义控件的变量范围可以直接填写变量的最大和最小,在此编程中的最大是10,最小是1。这就给编程写语句带来了方便。 

程序的设计思想和内容

(一)算法一:


24点游戏的算法,其中最主要的思想就是穷举法。所谓穷举法就是列出4个数字加减乘除的各种可能性。我们可以将表达式分成以下几种:首先我们将4个数设为a,b,c,d,,将其排序列出四个数的所有排序序列组合(共有A44=24种组合)。再进行符号的排列表达式,其中算术符号有+,—,*,/,(,)。其中有效的表达式有a*(b-c/b),a*b-c*d,等等。列出所有有效的表达式。其中我们用枚举类型将符号定义成数字常量。如下是我对穷举法的一种编程语言。在编程的头部要对变量做下定义。其中a,b,c,d的范围是1到10。这就需要在定义变量的时候要有限制。在vc++中的MFC编程中,在定义控件的变量范围可以直接填写变量的最大和最小,在此编程中的最大是10,最小是1。这就给编程写语句带来了方便(因为其自动会生成语句)。下面我介绍下穷举法的主要实现,我们知道要实现24点的算法,就是通过4个数字,4个运算符号和2对括号(最多为2对),通过各种组合判断其结果是否为24。我们用a,b,c,d代替4个数字。考虑每种可能,总的算法就有7种可能。分别为:

1没括号的(形如a*b*c*d);

2有括号的(形如(a * b) * c * d);

3有括号的(形如(a * b * c) * d);

4有括号的(形如a * (b * c) * d);

5有括号的(形如(a * b) * (c * d));

6有括号的(形如((a * b) * c) * d);

7有括号的(形如(a * (b * c)) * d)。

接下来就是对每一种进行分析判断。

以上就是穷举法的基本实现算法

首先穷举的可行性问题。我把表达式如下分成三类:

1、 列出四个数的所有排序序列组合(共有A44=24种组合)。

2、 构筑一个函数,列出所有运算表达式。

3、 输入数据计算。

代码如下:

bool Game24Points1(int a, int b, int c, int d)
{
	flag=false;
	float x=a;
	float y=b;
	float z=c;
	float w=d;
	flag=Calculate(x,y,z,w);
	if (flag==true)
	{
		cout<<"\n成功!"<<endl;
		return true;
	}
	else
	{
		cout<<"失败!"<<endl;
		return false;
	}
}
bool Calculate(float x, float y, float z, float w)
{
	if (x+y+z+w==24)
	{
		cout<<x<<"+"<<y<<"+"<<z<<"+"<<w<<"=24"<<endl;  
		return true;
	}
	else if (x+y+z-w==24) 
	{
		cout<<x<<"+"<<y<<"+"<<z<<"-"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x+y)*(z+w)==24) 
	{
		cout<<"("<<x<<"+"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;  
		return true;
	}
	else if ((x-y)*(z+w)==24) 
	{
		cout<<"("<<x<<"-"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;  
		return true;
	}
	else if ((x-y)*(z-w)==24) 
	{
		cout<<"("<<x<<"-"<<y<<")*("<<z<<"-"<<w<<")=24"<<endl; 
		return true;
	} 
	else if ((x+y+z)*w==24) 
	{
       cout<<"("<<x<<"+"<<y<<"+"<<z<<")*"<<w<<"=24"<<endl;  
	   return true;
	}
	else if ((x-y-z)*w==24) 
	{
		cout<<"("<<x<<"-"<<y<<"-"<<z<<")*"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x+y-z)*w==24) 
	{
		cout<<"("<<x<<"+"<<y<<"-"<<z<<")*"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x*y*z)/w==24) 
	{
		cout<<"("<<x<<"*"<<y<<"*"<<z<<")/"<<w<<"=24"<<endl; 
		return true;
	} 
	else if((x*y)*(z+w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;
		return true;
	}  
	else if ((x*y)*(z-w)==24)
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<"-"<<w<<")=24"<<endl; 
return true;
	}
	else if ((x*y)*z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<")-"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)*z+w==24) 
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<")+"<<w<<"=24"<<endl;  
return true;
	}
	else if (x*y*z*w==24) 
	{
cout<<x<<"*"<<y<<"*"<<z<<"*"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x+y)+(z/w)==24) 
	{
cout<<"("<<x<<"+"<<y<<")+("<<z<<"/"<<w<<")"<<"=24"<<endl;
return true;
	}  
	else if ((x+y)*(z/w)==24) 
	{
cout<<"("<<x<<"+"<<y<<")*("<<z<<"/"<<w<<")"<<"=24"<<endl;  
return true;
	}
	else if ((x*y)+z+w==24) 
	{
cout<<"("<<x<<"*"<<y<<")+"<<z<<"+"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)+z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")+"<<z<<"-"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)-(z/w)==24)
	{
 cout<<"("<<x<<"*"<<y<<")-("<<z<<"/"<<w<<")"<<"=24"<<endl;
 return true;
	}  
	else if ((x*y)+(z/w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")-("<<z<<"/"<<w<<")"<<"=24"<<endl; 
return true;
	}
	else if ((x*y)-z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")-"<<z<<"-"<<w<<"=24"<<endl;
return true;
	}  
	else if ((x*y)+(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")+("<<z<<"*"<<w<<")"<<"=24"<<endl;  
return true;
	}
	else if ((x*y)-(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")-("<<z<<"*"<<w<<")"<<"=24"<<endl; 
return true;
	} 
	else if ((x*y)/(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")/("<<z<<"*"<<w<<")"<<"=24"<<endl; 
return true;
	} 
	else if ((x*y)/(z-w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")/("<<z<<"-"<<w<<")"<<"=24"<<endl; 
		return true;

	} 
	else if ((x*y)/(z+w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")/("<<z<<"+"<<w<<")"<<"=24"<<endl;  
		return true;
	}
	else cout<<"不可以组成24"<<endl;  
	return false;   
}



(二)算法二:


24点游戏的算法,还有另外一种算法。

把多元运算转化为两元运算,先从四个数中取出两个数进行运算,然后把运算结果和第三个数进行运算,再把结果与第四个数进行运算。在求表达式的过程中,最难处理的就是对括号的处理,而这种思路很好的避免了对括号的处理。基于这种思路的一种算法:

因为能使用的4种运算符 – * / 都是2元运算符,所以本文中只考虑2元运算符。2元运算符接收两个参数,输出计算结果,输出的结果参与后续的计算。

  由上所述,构造所有可能的表达式的算法如下:

  (1) 将4个整数放入数组中

  (2) 在数组中取两个数字的排列,共有 P(4,2) 种排列。对每一个排列,

  (2.1) 对 – * / 每一个运算符,

  (2.1.1) 根据此排列的两个数字和运算符,计算结果

  (2.1.2) 改表数组:将此排列的两个数字从数组中去除掉,将 2.1.1 计算的结果放入数组中

  (2.1.3) 对新的数组,重复步骤 2

  (2.1.4) 恢复数组:将此排列的两个数字加入数组中,将 2.1.1 计算的结果从数组中去除掉

  可见这是一个递归过程。步骤 2 就是递归函数。当数组中只剩下一个数字的时候,这就是表达式的最终结果,此时递归结束。

  在程序中,一定要注意递归的现场保护和恢复,也就是递归调用之前与之后,现场状态应该保持一致。在上述算法中,递归现场就是指数组,2.1.2 改变数组以进行下一层递归调用,2.1.3 则恢复数组,以确保当前递归调用获得下一个正确的排列。

  括号 () 的作用只是改变运算符的优先级,也就是运算符的计算顺序。所以在以上算法中,无需考虑括号。括号只是在输出时需加以考虑。

bool Game24Points(int a, int b, int c, int d)
{
	//TODO: Add codes here ...
	flag=false;

	number[0]=a;
	number[1]=b;
	number[2]=c;
	number[3]=d;
	
	for (int i=0;i<CONT;i++)
	{
		char ch[20];
		itoa(number[i],ch,10);
		expression[i]=ch;
	}
	 Find(CONT);
	if (flag==true)
	{
		cout<<"\n成功!"<<endl;
		cout<<"共有计算方法: "<<count<<endl;
		return true;
	}
	else
	{
		cout<<"失败!"<<endl;
		return false;
	}
}
void Find(int n)
{
	if (n==1)
	{
		if (abs(number[0]-VALUE)<=EPP)
		{
			flag=true;
			cout<<expression[0]<<"\t\t";
			count++;
			if ((count%3)==0)
			{
				cout<<endl;
			}
		}
	}
	for (int i=0;i<n;i++)
	{
		for (int j=i+1;j<n;j++)
		{
			double a,b;
			string expressiona,expressionb;
			a=number[i];// 保存起来,在方法最后再恢复,以便继续计算
			b=number[j];// 保存起来,在方法最后再恢复,以便继续计算 
			number[j]=number[n-1];// 将最后一个数挪过来 
			expressiona=expression[i];// 保存起来,在方法最后再恢复,以便继续计算
			expressionb=expression[j];// 保存起来,在方法最后再恢复,以便继续计算
			expression[j]=expression[n-1];// 将最后一个式子挪过来
			expression[i]='('+expressiona+'+'+expressionb+')';// 看看加法能否算出,如果能算
			number[i]=a+b;
			Find(n-1);
			expression[i]='('+expressiona+'-'+expressionb+')';
			number[i]=a-b;
			Find(n-1);
			expression[i]='('+expressiona+'-'+expressionb+')';
			number[i]=b-a;
			Find(n-1);
			expression[i]='('+expressiona+'*'+expressionb+')';
			number[i]=a*b;
			Find(n-1);
			if (b!=0)
			{
				expression[i]='('+expressiona+'/'+expressionb+')';
				number[i]=a/b;
				Find(n-1);
			}
			if (a!=0)
			{
				expression[i]='('+expressiona+'/'+expressionb+')';
				number[i]=b/a;
				Find(n-1);
			}
			//如果以上的加、减、乘、除都不能得到有效的结果,则恢复数据进行下一轮的计算。   
			number[i]=a;// 恢复  
			number[j]=b;
			expression[i]=expressiona;
			expression[j]=expressionb;
		}
	}
}
完整代码如下:

head.h

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
const double  EPP=1e-6;
const int CONT=4;
int count=0;
const int VALUE=24;
bool flag=false;
double number[CONT];
string expression[CONT];
void Find(int n);
bool Game24Points(int a, int b, int c, int d);
bool Game24Points1(int a, int b, int c, int d);
bool Calculate(float x, float y, float z, float w);

main.cpp

#include "head.h"
void main()
{
	int a;
	int b;
	int c;
	int d;
	cin>>a>>b>>c>>d;
	//cout<<Game24Points(a,b,c,d)<<endl;
	cout<<Game24Points1(a,b,c,d);
}

bool Game24Points(int a, int b, int c, int d)
{
	//TODO: Add codes here ...
	flag=false;

	number[0]=a;
	number[1]=b;
	number[2]=c;
	number[3]=d;
	
	for (int i=0;i<CONT;i++)
	{
		char ch[20];
		itoa(number[i],ch,10);
		expression[i]=ch;
	}
	 Find(CONT);
	if (flag==true)
	{
		cout<<"\n成功!"<<endl;
		cout<<"共有计算方法: "<<count<<endl;
		return true;
	}
	else
	{
		cout<<"失败!"<<endl;
		return false;
	}
}
void Find(int n)
{
	if (n==1)
	{
		if (abs(number[0]-VALUE)<=EPP)
		{
			flag=true;
			cout<<expression[0]<<"\t\t";
			count++;
			if ((count%3)==0)
			{
				cout<<endl;
			}
		}
	}
	for (int i=0;i<n;i++)
	{
		for (int j=i+1;j<n;j++)
		{
			double a,b;
			string expressiona,expressionb;
			a=number[i];// 保存起来,在方法最后再恢复,以便继续计算
			b=number[j];// 保存起来,在方法最后再恢复,以便继续计算 
			number[j]=number[n-1];// 将最后一个数挪过来 
			expressiona=expression[i];// 保存起来,在方法最后再恢复,以便继续计算
			expressionb=expression[j];// 保存起来,在方法最后再恢复,以便继续计算
			expression[j]=expression[n-1];// 将最后一个式子挪过来
			expression[i]='('+expressiona+'+'+expressionb+')';// 看看加法能否算出,如果能算
			number[i]=a+b;
			Find(n-1);
			expression[i]='('+expressiona+'-'+expressionb+')';
			number[i]=a-b;
			Find(n-1);
			expression[i]='('+expressiona+'-'+expressionb+')';
			number[i]=b-a;
			Find(n-1);
			expression[i]='('+expressiona+'*'+expressionb+')';
			number[i]=a*b;
			Find(n-1);
			if (b!=0)
			{
				expression[i]='('+expressiona+'/'+expressionb+')';
				number[i]=a/b;
				Find(n-1);
			}
			if (a!=0)
			{
				expression[i]='('+expressiona+'/'+expressionb+')';
				number[i]=b/a;
				Find(n-1);
			}
			//如果以上的加、减、乘、除都不能得到有效的结果,则恢复数据进行下一轮的计算。   
			number[i]=a;// 恢复  
			number[j]=b;
			expression[i]=expressiona;
			expression[j]=expressionb;
		}
	}
}
bool Game24Points1(int a, int b, int c, int d)
{
	flag=false;
	float x=a;
	float y=b;
	float z=c;
	float w=d;
	flag=Calculate(x,y,z,w);
	if (flag==true)
	{
		cout<<"\n成功!"<<endl;
		return true;
	}
	else
	{
		cout<<"失败!"<<endl;
		return false;
	}
}
bool Calculate(float x, float y, float z, float w)
{
	if (x+y+z+w==24)
	{
		cout<<x<<"+"<<y<<"+"<<z<<"+"<<w<<"=24"<<endl;  
		return true;
	}
	else if (x+y+z-w==24) 
	{
		cout<<x<<"+"<<y<<"+"<<z<<"-"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x+y)*(z+w)==24) 
	{
		cout<<"("<<x<<"+"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;  
		return true;
	}
	else if ((x-y)*(z+w)==24) 
	{
		cout<<"("<<x<<"-"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;  
		return true;
	}
	else if ((x-y)*(z-w)==24) 
	{
		cout<<"("<<x<<"-"<<y<<")*("<<z<<"-"<<w<<")=24"<<endl; 
		return true;
	} 
	else if ((x+y+z)*w==24) 
	{
       cout<<"("<<x<<"+"<<y<<"+"<<z<<")*"<<w<<"=24"<<endl;  
	   return true;
	}
	else if ((x-y-z)*w==24) 
	{
		cout<<"("<<x<<"-"<<y<<"-"<<z<<")*"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x+y-z)*w==24) 
	{
		cout<<"("<<x<<"+"<<y<<"-"<<z<<")*"<<w<<"=24"<<endl;  
		return true;
	}
	else if ((x*y*z)/w==24) 
	{
		cout<<"("<<x<<"*"<<y<<"*"<<z<<")/"<<w<<"=24"<<endl; 
		return true;
	} 
	else if((x*y)*(z+w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")*("<<z<<"+"<<w<<")=24"<<endl;
		return true;
	}  
	else if ((x*y)*(z-w)==24)
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<"-"<<w<<")=24"<<endl; 
return true;
	}
	else if ((x*y)*z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<")-"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)*z+w==24) 
	{
cout<<"("<<x<<"*"<<y<<")*("<<z<<")+"<<w<<"=24"<<endl;  
return true;
	}
	else if (x*y*z*w==24) 
	{
cout<<x<<"*"<<y<<"*"<<z<<"*"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x+y)+(z/w)==24) 
	{
cout<<"("<<x<<"+"<<y<<")+("<<z<<"/"<<w<<")"<<"=24"<<endl;
return true;
	}  
	else if ((x+y)*(z/w)==24) 
	{
cout<<"("<<x<<"+"<<y<<")*("<<z<<"/"<<w<<")"<<"=24"<<endl;  
return true;
	}
	else if ((x*y)+z+w==24) 
	{
cout<<"("<<x<<"*"<<y<<")+"<<z<<"+"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)+z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")+"<<z<<"-"<<w<<"=24"<<endl;  
return true;
	}
	else if ((x*y)-(z/w)==24)
	{
 cout<<"("<<x<<"*"<<y<<")-("<<z<<"/"<<w<<")"<<"=24"<<endl;
 return true;
	}  
	else if ((x*y)+(z/w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")-("<<z<<"/"<<w<<")"<<"=24"<<endl; 
return true;
	}
	else if ((x*y)-z-w==24) 
	{
cout<<"("<<x<<"*"<<y<<")-"<<z<<"-"<<w<<"=24"<<endl;
return true;
	}  
	else if ((x*y)+(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")+("<<z<<"*"<<w<<")"<<"=24"<<endl;  
return true;
	}
	else if ((x*y)-(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")-("<<z<<"*"<<w<<")"<<"=24"<<endl; 
return true;
	} 
	else if ((x*y)/(z*w)==24) 
	{
cout<<"("<<x<<"*"<<y<<")/("<<z<<"*"<<w<<")"<<"=24"<<endl; 
return true;
	} 
	else if ((x*y)/(z-w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")/("<<z<<"-"<<w<<")"<<"=24"<<endl; 
		return true;

	} 
	else if ((x*y)/(z+w)==24) 
	{
		cout<<"("<<x<<"*"<<y<<")/("<<z<<"+"<<w<<")"<<"=24"<<endl;  
		return true;
	}
	else cout<<"不可以组成24"<<endl;  
	return false;   
}

技术分享


本文参考:

http://blog.csdn.net/wangqiulin123456/article/details/8145545

24点算法

标签:

原文地址:http://blog.csdn.net/sinat_24520925/article/details/45691159

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!