Bootstrap

c++实现计算二十四点--zj

c++实现计算二十四点–zj

首先,要感谢vaintwytC++实现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;
}

谢谢–zhengjun

;