算二十四点

众所周知,24点是一款老少皆宜的游戏。但是计算二十四点总是一件很头秃的事。

因此,是时候来写一个代码来实现自动计算24点了!(洛谷有原题 P1236)

首先,我们要制定策略——怎么样才能快速算出24呢?

我相信肯定有很多大佬会说:凑4,6,凑3,8,这样算得快!

BUT——这并不是绝对的,有的时候可以凑出24的因数,但是却无法解决问题

结合计算机计算速度快,制定上述策略又会使代码冗长(我是不会告诉你们我不想写的),

因此,我们可以使用暴力枚举!

(怎么枚举呢?)

废话,随便选两个数字做四则运算,只保留结果和运算过程,再删除这两个数。

总而言之,我们的策略就是——没有策略!

下面是代码(我就知道你们只想看这个,反正思路也很简单) 

​
#include<bits/stdc++.h>
using namespace std;
int cnt[10];//cnt数组用来存储数字

bool v[10];
//因为我们无法真正删除一个数字,且在回溯之后会重新用到这个数字,
//因此就用一个bool数组标记这个数字是否已经参与运算且不是结果。

string toa, tob, shi;//分别表示第一个、第二个参与运算的数字和算式
string ans[10];//存放运算步骤
int ansi = 0;

//第一步工作完成,开工!!!

void makejia(int a, int b) {//加法运算
	int e = max(cnt[a], cnt[b]);
	int f = min(cnt[a], cnt[b]);//大的数字在前(洛谷题目的要求)
	toa = to_string(e);
	tob = to_string(f);//转string
	int c = e + f;
	cnt[a] = c;//把运算结果存放在cnt[a]中
	string toans = to_string(c);
	shi = toa + "+" + tob + "=" + toans;//变成算式
	ans[ansi++] = shi;//存储
}//下面三个同理,只是运算不一样而已
void makejian(int a, int b) {
	toa = to_string(cnt[a]);
	tob = to_string(cnt[b]);
	int c = cnt[a] - cnt[b];
	cnt[a] = c;
	string toans = to_string(c);
	shi = toa + "-" + tob + "=" + toans;
	ans[ansi++] = shi;
}
void makecheng(int a, int b) {
	int e = max(cnt[a], cnt[b]);
	int f = min(cnt[a], cnt[b]);
	toa = to_string(e);
	tob = to_string(f);
	int c = e * f;
	cnt[a] = c;
	string toans = to_string(c);
	shi = toa + "*" + tob + "=" + toans;
	ans[ansi++] = shi;
}
void makechu(int a, int b) {
	toa = to_string(cnt[a]);
	tob = to_string(cnt[b]);
	int c = cnt[a] / cnt[b];
	cnt[a] = c;
	string toans = to_string(c);
	shi = toa + "/" + tob + "=" + toans;
	ans[ansi++] = shi;
}

//第二步完成,下面就是最后阶段!!!

void dfs() {//在本人眼里,大概是一个dfs

	if (ansi==3) {//参与完三次运算之后肯定只剩一个数字了
		for (int i = 1; i <= 4; i++) {
			if (!v[i] && cnt[i] == 24) {
				for (int j = 0; j < ansi; j++) {
					cout << ans[j] << endl;
				}
				exit(0);
			}
		}
		return;
	}
	//这里是重头戏,也是最容易手误(吃席)的地方!!!
	for (int i = 1; i <= 4; i++) {
		if (v[i]) continue;//
		for (int j = i + 1; j <= 4; j++) {
			if (v[j]) continue;//v数组就在这儿发挥用场

			v[j] = 1;//(别忘了,不然v数组就没用了!)
			makejia(i, j);//处理
			dfs();//继续深搜
			v[j] = 0;
			cnt[i] -= cnt[j];
			ansi--;//日常回溯
            //下方同理

			if (cnt[i] - cnt[j] > 0) {//不让出现负数
				v[j] = 1;
				makejian(i, j);
				dfs();
				v[j] = 0;
				cnt[i] += cnt[j];
				ansi--;
			}

			if (cnt[j] - cnt[i] > 0) {
				v[i] = 1;
				makejian(j, i);
				dfs();
				v[i] = 0;
				cnt[j] += cnt[i];
				ansi--;
			}

			v[j] = 1;
			makecheng(i, j);
			dfs();
			v[j] = 0;
			cnt[i] /= cnt[j];
			ansi--;

			if (cnt[i] % cnt[j] == 0) {//不让出现小数
				v[j] = 1;
				makechu(i, j);
				dfs();
				v[j] = 0;
				cnt[i] *= cnt[j];
				ansi--;
			}

			if (cnt[j] % cnt[i] == 0) {
				v[i] = 1;
				makechu(j, i);
				dfs();
				v[i] = 0;
				cnt[j] *= cnt[i];
				ansi--;
			}
		}
	}
}
signed main() {
	for (int i = 1; i <= 4; i++) cin >> cnt[i];
	dfs();
	cout << "No answer!";
	return 0;
}

​

现在,让我们来试(逝)一试(逝)

合理,恒河里~~~ 

总结:思路不算困难,但是需要耐心与细心才能写出正确的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值