特性:数字数量、目标答案不限,当然数据大了会很慢...

   基本可以去除所有本质相同的表达式...至少能等出结果的数据规模可以。。

安卓: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++版本]无聊拿去玩的更多相关文章

  1. Mozilla Firefox 24.0 Beta 5 发布

    Mozilla今天将Firefox 24.0 Beta 5版本放到了FTP的release目录,新版开始全面支持OS X 10.7全新的滚动条样式,禁止网站插件运行的功能出现在任务栏左侧,调整了界面U ...

  2. 0316-复利计算器3.0---release

    目录       一.项目简介       二.Github链接推送       三.客户需求       四.需求分析       五.项目设计       六.完成效果       七.JUnit ...

  3. 0406.复利计算器5.0版-release

    复利计算器5.0-release 目录 项目简介 Github链接推送 客户需求 新增需求分析 项目设计 效果演示 操作说明 程序结构 结对分工 合作照片 总结 1.项目简介 项目名称:复利计算器 目 ...

  4. 0414-复利计算器6.0.Release

    复利计算器6.0--Release 前言 本次复利计算器的版本更新,主要有以下内容的完善: 1.优化了Web版的页面,提供了更舒服美观的用户体现. 2.新增了移动端(安卓)app版本. 版本信息 项目 ...

  5. PhoneGap搭建运行环境(3.2版本)

    一. 1.准备环境nodejs(http://nodejs.org/download/) 2.ant(http://ant.apache.org/bindownload.cgi) 3.Android ...

  6. eclipse版本选择

    Eclipse最初是由IBM公司开发的替代商业软件Visual Age for Java的下一代IDE开发环境,2001年11月贡献给开源社区,现在它由非营利软件供应商联盟Eclipse基金会. Ec ...

  7. 微信小程序计算器Bug版=-=(笔记)

    微信小程序计算器BUG版本 无APPID的测试号登录,先在app.json中更改路径,以及修改头部信息. 首先一个输入框字段用{{screenData}} 功能可以退格,清屏,正负号,正常操作加减乘除 ...

  8. CentOS7编译安装MySQL5.7.24

    目录 安装依赖 安装boost 编译安装MySQL 配置 登录MySQL,修改密码 安装依赖 (1)cmake是新版MySQL的编译工具 sudo yum install gcc gcc-c++ pc ...

  9. Android 6.0 7.0 8.0 一个简单的app内更新版本-okgo app版本更新

    登陆时splash初始页调用接口检查app版本.如有更新,使用okGo的文件下载,保存到指定位置,调用Android安装apk. <!-- Android 8.0 (Android O)为了针对 ...

随机推荐

  1. P3822 [NOI2017]整数

    传送门 shadowice大佬已经写的非常详细了我就不再写一遍了-- //minamoto #include<bits/stdc++.h> #define u unsigned int # ...

  2. [TJOI2012]桥

    Description 有n个岛屿,m座桥,每座桥连通两座岛屿,桥上会有一些敌人,玩家只有消灭了桥上的敌人才能通过,与此同时桥上的敌人会对玩家造成一定伤害.而且会有一个大Boss镇守一座桥,以玩家目前 ...

  3. Storm编程入门API系列之Storm的定时任务实现

    概念,见博客 Storm概念学习系列之storm的定时任务 Storm的定时任务,分为两种实现方式,都是可以达到目的的. 我这里,分为StormTopologyTimer1.java   和  Sto ...

  4. Kafka~服务端几个常用的命令

    在Centos上安装和部署完成kafka之后,我们就可以向服务端推消息和消费它了,今天主要聊几个常用的命令,比建立topic,从broken显示所有topics列表,向broken发消息,从broke ...

  5. [转]ASP.NET MVC的帮助类HtmlHelper和UrlHelper

    本文转自:http://www.cnblogs.com/greatandforever/archive/2010/04/20/1715914.html?login=1 在ASP.NET MVC框架中没 ...

  6. NodeJS、NPM安装配置步骤

    安装NodeJS和NPM 1.Node JS 官网下载地址 https://nodejs.org/en/download/ 2.安装完后,使用cmd 命令输入两个命令,查看安装状态 node -v n ...

  7. Angular——作用域

    基本介绍 应用App是无法嵌套的,但是controller是可以嵌套的,每个controller都会对应一个模型(model)也就是$scope对象,不同层级的controller下的$scope遍产 ...

  8. Probabilistic locking in SQLite

    In SQLite, a reader/writer lock mechanism is required to control the multi-process concurrent access ...

  9. spring中配置数据源

    spring中配置数据源的几种常见方式: #mysql 数据库配置(jdbc.properties) jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.u ...

  10. Spartan6系列之芯片配置模式详解

    1.   配置概述 Spartan6系列FPGA通过把应用程序数据导入芯片内部存储器完成芯片的配置.Spart-6 FPGA可以自己从外部非易失性存储器导入编程数据,或者通过外界的微处理器.DSP等对 ...