c++实现计算二十四点–zj
首先,要感谢vaintwyt的C++实现24点算法,使我有了灵感,编出了计算24点的程序。
不懂的,直接去刚才第二个链接里看。
上代码
#include<bits/stdc++.h>
#define f(x) for(x=1;x<=4;x++)
using namespace std;
map<string,int> q;
char o[5]="+-*/";
int tot=0;
bool flag=false;
double myabs(double x){return x>0?x:-x;}
bool check(double x){return myabs(x-24)<0.000001;}
double Add(double a, double b){return a+b;}
double Sub(double a, double b){return a-b;}
double Mul(double a, double b){return a*b;}
double Div(double a, double b){if(!b)return -100000;return a/b;}
double(*op[4])(double,double) = {Add, Sub, Mul, Div};//函数指针。C++确实强大
void Game24Points(double a, double b, double c, double d)
{
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
{
for(int k=0; k<4; k++)
{
//((a#b)#c)#d
double ret = op[k](op[j](op[i](a, b), c) , d);
if(check(ret))
{
printf("\n第%d种:\n((%0.0lf%c%0.0lf)%c%0.0lf)%c%0.0lf=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//(a#(b#c))#d
ret = op[k](op[i](a, op[j](b, c)) , d);
if(check(ret))
{
printf("\n第%d种:\n(%0.0lf%c(%0.0lf%c%0.0lf))%c%0.0lf=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//a#((b#c)#d)
ret = op[i](a, op[k](op[j](b, c) , d));
if(check(ret))
{
printf("\n第%d种:\n%0.0lf%c((%0.0lf%c%0.0lf)%c%0.0lf)=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//(a#b)#(c#d)
ret = op[j](op[i](a, b), op[k](c, d));
if(check(ret))
{
printf("\n第%d种:\n(%0.0lf%c%0.0lf)%c(%0.0lf%c%0.0lf)=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//a#(b#(c#d))
ret = op[i](a, op[j](b, op[k](c, d)));
if(check(ret))
{
printf("\n第%d种:\n%0.0lf%c(%0.0lf%c(%0.0lf%c%0.0lf))=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
}
}
}
}
int main()
{
double a[5];
int i,j,k;
f(i)cin>>a[i];
bool s=false;
f(i)
{
f(j)
{
if(i==j)continue;
f(k)
{
if(i==k||i==10-i-j-k||j==k||j==10-j-k-i||k==10-j-i-k)
continue;
string a1,b1,c1,d1,f1;
a1=char(a[i]+'0');b1=char(a[j]+'0');c1=char(a[k]+'0');d1=char(a[10-i-j-k]+'0');
f1=a1+' '+b1+' '+c1+' '+d1;
if(q[f1])
continue;
q[f1]=1;
Game24Points(a[i],a[j],a[k],a[10-i-j-k]);
}
}
}
if(flag)
printf("\n共%d个解\n",tot);
else printf("此题无解\n");
return 0;
}
接着,我又想。
1 2 2 3不是可以**(2^(2+1))*3**的吗?我就添加了乘方和对数运算。
代码
#include<bits/stdc++.h>
#define f(x) for(x=1;x<=4;x++)
using namespace std;
map<string,int> q;
char o[8]="+-*/^lg";
int tot=0;
bool flag=false;
double myabs(double x){return x>0?x:-x;}
double mylog(double a,double b)
{
if(b==1)return 0;
if(a<=1&&a<b)return -100000;
int ans=0;
double t=1;
while(t<b)
{
t*=a;
ans++;
}
if(t==b)return ans;
return -100000;
}
bool check(double x){return myabs(x-24)<0.000001;}
double Add(double a, double b){return a+b;}
double Sub(double a, double b){return a-b;}
double Mul(double a, double b){return a*b;}
double Div(double a, double b){if(!b)return -100000;return a/b;}
double Pow(double a, double b){return pow(a,b);}
double Log(double a, double b){return mylog(a,b);}
double Sqrt(double a,double b)
{
int l=0,r=b+1,mid;
while(l+1<r)
{
mid=(l+r)>>1;
if(pow(mid,a)>=b)r=mid;
else l=mid;
}
if(pow(r,a)==b)return r;
return -100000;
}
double(*op[7])(double,double) = {Add, Sub, Mul, Div, Pow, Log, Sqrt};//函数指针。C++确实强大
void Game24Points(double a, double b, double c, double d)
{
for(int i=0; i<7; i++)
{
for(int j=0; j<7; j++)
{
for(int k=0; k<7; k++)
{
//((a#b)#c)#d
double ret = op[k](op[j](op[i](a, b), c) , d);
if(check(ret))
{
printf("\n第%d种:\n((%0.0lf%c%0.0lf)%c%0.0lf)%c%0.0lf=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//(a#(b#c))#d
ret = op[k](op[i](a, op[j](b, c)) , d);
if(check(ret))
{
printf("\n第%d种:\n(%0.0lf%c(%0.0lf%c%0.0lf))%c%0.0lf=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//a#((b#c)#d)
ret = op[i](a, op[k](op[j](b, c) , d));
if(check(ret))
{
printf("\n第%d种:\n%0.0lf%c((%0.0lf%c%0.0lf)%c%0.0lf)=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//(a#b)#(c#d)
ret = op[j](op[i](a, b), op[k](c, d));
if(check(ret))
{
printf("\n第%d种:\n(%0.0lf%c%0.0lf)%c(%0.0lf%c%0.0lf)=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
//a#(b#(c#d))
ret = op[i](a, op[j](b, op[k](c, d)));
if(check(ret))
{
printf("\n第%d种:\n%0.0lf%c(%0.0lf%c(%0.0lf%c%0.0lf))=24\n",++tot,a,o[i],b,o[j],c,o[k],d);
flag=true;
}
}
}
}
}
int main()
{
printf("请输入你要进行运算的4个数:\n");
double a[5];
int i,j,k;
f(i)printf("\n第%d个:",i),cin>>a[i];
bool s=false;
f(i)
{
f(j)
{
if(i==j)continue;
f(k)
{
if(i==k||i==10-i-j-k||j==k||j==10-j-k-i||k==10-j-i-k)
continue;
string a1,b1,c1,d1,f1;
a1=char(a[i]+'0');b1=char(a[j]+'0');c1=char(a[k]+'0');d1=char(a[10-i-j-k]+'0');
f1=a1+' '+b1+' '+c1+' '+d1;
if(q[f1])
continue;
q[f1]=1;
Game24Points(a[i],a[j],a[k],a[10-i-j-k]);
}
}
}
if(flag)
{
printf("\n共%d个解\n",tot);
printf("\n温馨提示:\n1.\"^\"为乘方运算,a^b=a的b次方\n2.\"l\"为对数运算,alb=log a(b)\n3.\"g\"为开方运算,agb=b的a次方根\n");
}
else printf("此题无解\n");
return 0;
}
升级版(支持多个数和x点)
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
char p[6]=" +*-/";
int tot,n,used[1001],b[1001][3],f[1001];
double k[1001],a[1001],ans;
bool check(double x){
if(x<ans)return ans-x<1e-5;
return x-ans<1e-5;
}
double get(int op,double x,double y){
if(op==1)return x+y;
if(op==2)return x*y;
if(op==3)return x-y;
if(op==4)return x/y;
}
void put(double x){
double s=x-round(x)*1.0;
if(s<0)s=-s;
if(s<1e-5)printf("%.0lf",x);
else printf("%.6lf",x);
}
void print(){
printf("找到答案了:\n");
double c[1001];
memcpy(c,k,sizeof(k));
for(int i=1;i<n;i++){
put(c[b[i][0]]);
printf("%c",p[b[i][1]]);
put(c[b[i][2]]);
printf("=");
put(get(b[i][1],c[b[i][0]],c[b[i][2]]));
printf("\n");
c[b[i][0]]=get(b[i][1],c[b[i][0]],c[b[i][2]]);
}
}
void dfs(int x){
if(x==n){
int sum=0,flag=0;
for(int i=1;i<=n;i++){
if(!used[i])sum++;
if(!used[i]&&check(a[i]))flag=1;
}
if(sum==1&&flag==1){
if(!tot)print();
tot++;
}
return;
}
for(int i=1;i<=n;i++){
if(used[i])continue;
for(int j=i+1;j<=n;j++){
if(used[j])continue;
for(int l=1;l<=2;l++){
double xx=a[i],y=a[j];
used[j]=1;
b[x][0]=i;b[x][1]=l;b[x][2]=j;
a[i]=get(l,xx,y);
dfs(x+1);
b[x][0]=b[x][1]=b[x][2]=0;
a[i]=xx;
used[j]=0;
}
}
}
for(int i=1;i<=n;i++){
if(used[i])continue;
for(int j=1;j<=n;j++){
if(used[j])continue;
if(i==j)continue;
for(int l=3;l<=4;l++){
double xx=a[i],y=a[j];
used[j]=1;
b[x][0]=i;b[x][1]=l;b[x][2]=j;
a[i]=get(l,xx,y);
dfs(x+1);
b[x][0]=b[x][1]=b[x][2]=0;
a[i]=xx;
used[j]=0;
}
}
}
}
int main(){
printf("请输入数的个数:");
scanf("%d",&n);
printf("请输入最终要得到的数:");
scanf("%lf",&ans);
for(int i=1;i<=n;i++)
printf("请输入第%d个数:",i),scanf("%lf",&a[i]),k[i]=a[i];
sort(a+1,a+1+n);
f[n]=n+1;
for(int i=n-1;i>=1;i--){
if(a[i]!=a[i+1])f[i]=i+1;
else f[i]=f[i+1];
}
dfs(1);
if(tot)printf("\n一共有%d个解",tot);
else printf("此题无解");
return 0;
}
最终版(使用分数输出,例如: a b \frac{a}{b} ba表示为 ( a / b ) (a/b) (a/b))
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
struct zj{
int z,m;
zj(){
z=0;m=1;
}
zj(int a,int b){
z=a;m=b;
}
friend void about(zj &x){
int a=gcd(x.z,x.m);
if(!a)return;
x.z/=a;
x.m/=a;
}
zj operator + (const zj &x)const{
int a=gcd(m,x.m);
if(!a)return zj(0,1);
return zj(z*x.m/a+x.z*m/a,m*x.m/a);
}
zj operator - (const zj &x)const{
int a=gcd(m,x.m);
if(!a)return zj(0,1);
return zj(z*x.m/a-x.z*m/a,m*x.m/a);
}
zj operator * (const zj &x)const{
zj a=zj(z*x.z,m*x.m);
about(a);
return a;
}
zj operator / (const zj &x)const{
zj a=zj(z*x.m,m*x.z);
about(a);
return a;
}
friend istream& operator >> (istream &in,zj &x){
int a;
in>>a;
x=zj(a,1);
return in;
}
friend ostream& operator << (ostream &out,const zj &x){
if(x.z%x.m==0){
out<<x.z/x.m;
return out;
}
zj k=x;
about(k);
out<<"("<<k.z<<"/"<<k.m<<")";
return out;
}
}k[1001],a[1001],ans;
char p[6]=" +*-/";
int n,used[1001],b[1001][3],f[1001];
bool check(zj x){
zj res=x-ans;
double s=(double)res.z/res.m;
if(s<0)s=-s;
return s<1e-5;
}
zj get(int op,zj x,zj y){
if(op==1)return x+y;
if(op==2)return x*y;
if(op==3)return x-y;
if(op==4)return x/y;
}
void print(){
printf("找到答案了:\n");
zj c[1001];
memcpy(c,k,sizeof(k));
for(int i=1;i<n;i++){
cout<<c[b[i][0]]<<p[b[i][1]]<<c[b[i][2]]<<"="<<get(b[i][1],c[b[i][0]],c[b[i][2]])<<"\n";
c[b[i][0]]=get(b[i][1],c[b[i][0]],c[b[i][2]]);
}
}
void dfs(int x){
if(x==n){
int sum=0,flag=0;
for(int i=1;i<=n;i++){
if(!used[i])sum++;
if(!used[i]&&check(a[i]))flag=1;
}
if(sum==1&&flag==1){
print();
exit(0);
}
return;
}
for(int i=1;i<=n;i++){
if(used[i])continue;
for(int j=i+1;j<=n;j++){
if(used[j])continue;
for(int l=1;l<=2;l++){
zj xx=a[i],y=a[j];
used[j]=1;
b[x][0]=i;b[x][1]=l;b[x][2]=j;
a[i]=get(l,xx,y);
dfs(x+1);
b[x][0]=b[x][1]=b[x][2]=0;
a[i]=xx;
used[j]=0;
}
}
}
for(int i=1;i<=n;i++){
if(used[i])continue;
for(int j=1;j<=n;j++){
if(used[j])continue;
if(i==j)continue;
for(int l=3;l<=4;l++){
zj xx=a[i],y=a[j];
used[j]=1;
b[x][0]=i;b[x][1]=l;b[x][2]=j;
a[i]=get(l,xx,y);
dfs(x+1);
b[x][0]=b[x][1]=b[x][2]=0;
a[i]=xx;
used[j]=0;
}
}
}
}
int main(){
printf("请输入数的个数:");
scanf("%d",&n);
printf("请输入最终要得到的数:");
cin>>ans;
for(int i=1;i<=n;i++)
printf("请输入第%d个数:",i),cin>>a[i],k[i]=a[i];
dfs(1);
printf("此题无解");
return 0;
}