C++24点——输出所有答案!易上手,无复杂操作!

感觉各位大佬们写得真的很一般啊,都没我这个蒟蒻好,很多功能都有限制。

24点其实就是4个数字+3个符号+5种加括号方式,没了,就这么简单,随随便便枚举就可以了。

现在我来讲讲我的思路和代码:

一、输入。

输入用了string数组in(本来可以用int的,但是那样的话就输入不了J、Q、K,还原度就低了),之后转化为double数组a里面(有人问为啥不用int——因为那样做的话,后面除法就没办法搞,比如5/2,本来是2.5,用int数组存就变成2了)。

二、判断一种情况是否有解。

还记得我开头讲的吗?24点其实就是4个数字+3个符号+5种加括号方式。4个数字是确定的,只需要枚举3个符号就可以了。

o1,o2,o3分别代表第1个,第2个和第3个符号:值为0就是加,1就是减,2就是乘,3就是除。

但是还有一点特别重要——括号!

其实括号不难,整来整去,总共就5种方式:

((AB)C)D  、 (AB)(CD) 、 (A(BC))D 、 A((BC)D) 、A(B(CD))

随随便便枚举下,就OK了。

三、列举所有情况。

本来想写全排列,怕你们看不懂(其实是想偷懒),想了想,就直接用系统自带的next_permutation函数枚举了。

四、输出。

这里我就不废话了,对应着的是哪种加括号方式就按哪种情况输出(详细处见代码)。

但是我的方法也有缺陷——有冗余括号(其实我可以在输出前加个判断的,但是太麻烦了)。

好了,思路说完了,上代码:

#include <bits/stdc++.h>
using namespace std;
const double eps=0.000001;//极小值
map<int,char> m={
  
  {0,'+'},{1,'-'},{2,'*'},{3,'/'}};//对应符号
string in[4];//因为有10,所以用string
double a[4];
int o1,o2,o3;//4个数字,3个符号
bool can_output=0;//是否有解
double calc(double x,int fh,double y);//计算x fh y
void output(int x);//输出
int main(){
	cout<<"请输入要计算24点的4个数字:"<<endl;
	cout<<"(A 1 2 3 4 5 6 7 8 9 10 J Q K中的一个)"<<endl;
	int T=1;
	//如需多测,将下面//cin>>T的注释删去即可
	//cin>>T;
	while(T--){
		for(int i=0;i<4;i++) cin>>in[i];
		bool is_right=0;
		for(int i=0;i<4;i++){
			do{
				is_right=1;
				//string转int:
				if(in[i]=="A") a[i]=1;
				else if(in[i]>="2"&&in[i]<="9") a[i]=double(in[i][0]-'0');
				else if(in[i]=="10") a[i]=10;
				else if(in[i]=="J") a[i]=11;
				else if(in[i]=="Q") a[i]=12;
				else if(in[i]=="K") a[i]=13;
				else{
					is_right=0;
					cout<<"第"<<i+1<<"个数字("<<in[i]<<")输入错误,请重输!"<<endl;
					cin>>in[i];
				}
			}while(!is_right);
		}
		sort(a,a+4);//排好序才能用next_permutation枚举
		do{
			//枚举3个符号:
			for(o1=0;o1<4;o1++){
				for(o2=0;o2<4;o2++){
					for(o3=0;o3<4;o3++){
						//5种情况判断:
						if(fabs(24.0-(calc(calc(calc(a[0],o1,a[1]),o2,a[2]),o3,a[3])))<=eps) output(0);
						if(fabs(24.0-(calc(calc(a[0],o1,a[1]),o2,calc(a[2],o3,a[3]))))<=eps) output(1);
						if(fabs(24.0-(calc(calc(a[0],o1,calc(a[1],o2,a[2])),o3,a[3])))<=eps) output(2);
						if(fabs(24.0-(calc(a[0],o1,calc(calc(a[1],o2,a[2]),o3,a[3]))))<=eps) output(3);
						if(fabs(24.0-(calc(a[0],o1,calc(a[1],o2,calc(a[2],o3,a[3])))))<=eps) output(4);
					}
				}
			}
		}while(next_permutation(a,a+4));//用next_permutation枚举4个数字的全排列
		if(!can_output) cout<<"无解";
	}
	return 0;
}
double calc(double x,int fh,double y){
	if(fh==0) return x+y;
	else if(fh==1) return x-y;
	else if(fh==2) return x*y;
	else if(fh==3&&y!=0) return x/y;//注意除数不能为0
}
void output(int x){
	can_output=1;
	//五种情况输出:
	if(x==0) cout<<("(("+in[0]+m[o1]+in[1]+")"+m[o2]+in[2]+")"+m[o3]+in[3]+"=24");
	else if(x==1) cout<<("("+in[0]+m[o1]+in[1]+")"+m[o2]+"("+in[2]+m[o3]+in[3]+")=24");
	else if(x==2) cout<<("("+in[0]+m[o1]+"("+in[1]+m[o2]+in[2]+"))"+m[o3]+in[3]+"=24");
	else if(x==3) cout<<(in[0]+m[o1]+"(("+in[1]+m[o2]+in[2]+")"+m[o3]+in[3]+")=24");
	else if(x==4) cout<<(in[0]+m[o1]+"("+in[1]+m[o2]+"("+in[2]+m[o3]+in[3]+"))=24");
	cout<<endl;
}

怎么样,有没有帮助?有的话就麻烦各位点赞+收藏吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值