[24点计算器][C++版本]无聊拿去玩
特性:数字数量、目标答案不限,当然数据大了会很慢...
基本可以去除所有本质相同的表达式...至少能等出结果的数据规模可以。。
安卓:http://yun.baidu.com/s/1slCGILn
程序用法:
输入n,tar,lim;分别表示n个数,目标答案,最多计算lim个解(0表示输出所有解)
然后输入n个数字
例: 4 24 3
1 2 3 4
表示4个数字1,2,3,4要算出24的前三个解
一般6个数找所有答案开O2需要一分半吧。。
思路(当然是爆枚咯。。。):
由于中缀表达式枚举括号比较麻烦,所以用后缀表达式枚举运算符,最后再把后缀转成中缀输出即可。
但这样还枚举不全,需要枚举数字的全排列再把运算符填进去。
这样虽然可以枚举所有情况,但是因为交换律的存在大量重复出现(比如2*3*4 3*2*4...)所以要去重。。
由于本人能力有限,,所以用了奇怪的方法,,不过效果还不错,方法如下。
随机生成若干个(程序里是4个)数组,和原数组匹配,然后用同样的运算符计算各个数组,把答案打包存进map有重复不输出即可
例:
比如当前枚举的运算方法是(a+b)/c*d
原数组:
w x y z ==>(w+x)/y*z
随机数组:
a[0][] a[0][] a[0][2] a[0][3] ==>(a[0][]+a[0][])/a[0][2]*a[0][3]=A
a[1][] a[1][] a[1][2] a[1][3] ==>(a[1][]+a[1][])/a[1][2]*a[1][3]=B
a[2][] a[2][] a[2][2] a[2][3] ==>(a[2][]+a[2][])/a[2][2]*a[2][3]=C
......
把{A,B,C,....}放到map里
当枚举到(b+a)/c*d的时候发现
x w y z ==>(x+w)/y*z
a[0][] a[0][] a[0][2] a[0][3] ==>(a[0][]+a[0][])/a[0][2]*a[0][3]=D
a[1][] a[1][] a[1][2] a[1][3] ==>(a[1][]+a[1][])/a[1][2]*a[1][3]=E
a[2][] a[2][] a[2][2] a[2][3] ==>(a[2][]+a[2][])/a[2][2]*a[2][3]=F
此时{A,B,C,...}=={D,E,F,...}说明(a+b)/c*d和(b+a)/c*d是同样的表达式,那么不输出即可。
代码如下
#include <bits/stdc++.h> using namespace std; const int base=; int n,a[],vec[],tar,trw=,Cnt;
int test[][],testb[][];
bool visited[]; const char op_list[]={'+','-','*','/'}; struct T
{
double aa,bb;
bool operator<(const T temp)const
{
if(fabs(aa-temp.aa)>1e-) return aa<temp.aa;
if(fabs(bb-temp.bb)>1e-) return bb<temp.bb;
return false;
}
}; struct Expr
{
string str;
char op;
Expr(){op=' ';}
}; vector<int> op[];
map<T,bool> Map; void Init_random_list()
{
srand(time());
for(int j=;j<;++j) for(int i=;i<n;++i) test[i][j]=rand()%(base*);
for(int i=;i<n;++i) for(int j=i+;j<n;++j)
if(a[i]==a[j]) for(int k=;k<;++k) test[j][k]=test[i][k];
return ;
}
double C()
{
stack<double> S;
stack<double> r[];
for(int i=;i<n;++i)
{
S.push(vec[i]);
for(int j=;j<(int)op[i].size();++j)
{
double t1=S.top(); S.pop();
double t2=S.top(); S.pop();
if(op[i][j]==) S.push(t2+t1);
if(op[i][j]==) S.push(t2-t1);
if(op[i][j]==) S.push(t2*t1);
if(op[i][j]==) S.push(t2/t1);
}
}
if(fabs(S.top()-(double)tar)<1e-)
{
for(int i=;i<n;++i)
{
for(int k=;k<;++k)
{
r[k].push(testb[i][k]);
for(int j=;j<(int)op[i].size();++j)
{
double t1=r[k].top(); r[k].pop();
double t2=r[k].top(); r[k].pop();
if(op[i][j]==) r[k].push(t2+t1);
if(op[i][j]==) r[k].push(t2-t1);
if(op[i][j]==) r[k].push(t2*t1);
if(op[i][j]==) r[k].push(t2/t1);
}
}
}
T temp=(T){r[].top(),r[].top()};
if(Map[temp])return -1e100;
Map[temp]=true;
}
return S.top();
} void Pr()
{
Cnt++; Expr temp;
stack<Expr> S; for(int i=;i<n;++i)
{
char temp_str[];
sprintf(temp_str,"%d",vec[i]);
temp.str=temp_str;
temp.op=' '; S.push(temp);
for(int j=;j<(int)op[i].size();++j)
{
Expr t1,t2;
t2=S.top(); S.pop();
t1=S.top(); S.pop();
if(op[i][j]> && (t1.op=='+' || t1.op=='-' || t2.op=='+' || t2.op=='-'))
{
if(t1.op=='+' || t1.op=='-') t1.str=" ( "+t1.str+" ) ";
if(t2.op=='+' || t2.op=='-') t2.str=" ( "+t2.str+" ) ";
temp.str=t1.str+' '+op_list[op[i][j]]+' '+t2.str;
temp.op=op_list[op[i][j]];
}
else temp.str=t1.str+' '+op_list[op[i][j]]+' '+t2.str,
temp.op=op_list[op[i][j]];
S.push(temp);
}
}
printf("%s\n",S.top().str.c_str());
return ;
} /* Violent enumeration operator */
void Calc(const int step,const int pos,const int lim)
{
if(step==n-)
{
if(fabs(C()-(double)tar)<1e-)
{
Pr();
if(Cnt==trw)throw ;
}
return ;
}
for(int i=max(pos,step+);i<n;++i)
{
for(int j=;j<=lim;++j)
{
op[i].push_back(j);
if(step+<=i) Calc(step+,i,lim);
op[i].pop_back();
}
}
return ;
} /* Violent enumeration Permutations */
void Dfs(const int step,const int lim)
{
if(step==n)
{
try{Calc(,,lim);}
catch(...){throw ;}
return ;
}
for(int i=;i<n;++i)
{
if(!visited[i])
{
visited[i]=true;
vec[step]=a[i];
for(int j=;j<;++j)
testb[step][j]=test[i][j];
Dfs(step+,lim);
visited[i]=false;
}
}
return ;
} int main()
{
printf("Size of Input:\t"); scanf("%d",&n);
printf("Target Result:\t"); scanf("%d",&tar);
printf("Result limits(0 for no limits): "); scanf("%d",&trw); printf("Input(32bits integers):\n");
for(int i=;i<n;++i) scanf("%d",&a[i]); clock_t start_time=clock();
Init_random_list(); printf("========================\n");
//这里会优先选择没有乘除的方案
//try{Dfs(0,0);}catch(...){}
//try{Dfs(0,1);}catch(...){}
//try{Dfs(0,2);}catch(...){}
try{Dfs(,);}catch(...){}
printf("========================\n"); printf("%d Results Found!\n",Cnt);
printf("%ldms Cost!\n",clock()-start_time);
return ;
}
[24点计算器][C++版本]无聊拿去玩的更多相关文章
- Mozilla Firefox 24.0 Beta 5 发布
Mozilla今天将Firefox 24.0 Beta 5版本放到了FTP的release目录,新版开始全面支持OS X 10.7全新的滚动条样式,禁止网站插件运行的功能出现在任务栏左侧,调整了界面U ...
- 0316-复利计算器3.0---release
目录 一.项目简介 二.Github链接推送 三.客户需求 四.需求分析 五.项目设计 六.完成效果 七.JUnit ...
- 0406.复利计算器5.0版-release
复利计算器5.0-release 目录 项目简介 Github链接推送 客户需求 新增需求分析 项目设计 效果演示 操作说明 程序结构 结对分工 合作照片 总结 1.项目简介 项目名称:复利计算器 目 ...
- 0414-复利计算器6.0.Release
复利计算器6.0--Release 前言 本次复利计算器的版本更新,主要有以下内容的完善: 1.优化了Web版的页面,提供了更舒服美观的用户体现. 2.新增了移动端(安卓)app版本. 版本信息 项目 ...
- PhoneGap搭建运行环境(3.2版本)
一. 1.准备环境nodejs(http://nodejs.org/download/) 2.ant(http://ant.apache.org/bindownload.cgi) 3.Android ...
- eclipse版本选择
Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下一代IDE开发环境,2001年11月贡献给开源社区,现在它由非营利软件供应商联盟Eclipse基金会. Ec ...
- 微信小程序计算器Bug版=-=(笔记)
微信小程序计算器BUG版本 无APPID的测试号登录,先在app.json中更改路径,以及修改头部信息. 首先一个输入框字段用{{screenData}} 功能可以退格,清屏,正负号,正常操作加减乘除 ...
- CentOS7编译安装MySQL5.7.24
目录 安装依赖 安装boost 编译安装MySQL 配置 登录MySQL,修改密码 安装依赖 (1)cmake是新版MySQL的编译工具 sudo yum install gcc gcc-c++ pc ...
- Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新
登陆时splash初始页调用接口检查app版本.如有更新,使用okGo的文件下载,保存到指定位置,调用Android安装apk. <!-- Android 8.0 (Android O)为了针对 ...
随机推荐
- ionic2.1.0 --beta3版本新建页面做弹框时遇到的问题
新建的页面需要在app.module.ts文件中定义.不然制作页面弹出效果是会报错.
- 微服务下,使用ELK做日志收集及分析
一.使用背景 目前项目中,采用的是微服务框架,对于日志,采用的是logback的配置,每个微服务的日志,都是通过File的方式存储在部署的机器上,但是由于日志比较分散,想要检查各个微服务是否有报错信息 ...
- javascript实现引用数据类型的深拷贝和浅拷贝详解
关于引用类型值的详解,请看另一篇随笔 https://www.cnblogs.com/jinbang/p/10346584.html 深拷贝和浅拷贝,也就是引用数据类型栈和堆的知识点.深浅拷贝的原型都 ...
- spring cloud config搭建说明例子(三)-添加actuator
添加心跳 服务端 ConfigServer pom.xml添加actuator包 <dependency> <groupId>org.springframework.cloud ...
- SQL 索引篇
索引介绍: 1.索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息. 数据库索引好比是一本书前面的目录, SQL Server的B树结构 2.加快数据库的查询速 ...
- 题解报告:hdu 1061 Rightmost Digit(快速幂取模)
Problem Description Given a positive integer N, you should output the most right digit of N^N. Input ...
- 对数组名取地址&a和 数组首地址a
#include <iostream> using namespace std; ] = {,,,,}; int main() { cout<<a<<" ...
- 【转】Spark:Master High Availability(HA)高可用配置的2种实现
原博文出自于: 感谢! Spark Standalone集群是Master-Slaves架构的集群模式,和大部分的Master-Slaves结构集群一样,存在着Master单点故障的问题.如何解决这个 ...
- mysqldump使用笔记
mysqldump备份简述 mysqldump可产生两种类型的输出文件,取决于是否选用 --tab=dir_name选项. 1.不使用 --tab=dir_name选项,mysqldump产生的数据文 ...
- sql 所有数据表中 插入字段
declare @tablename varchar(200)declare @sql varchar(2000)declare cur_t cursor forselect name from sy ...