众所周知,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;
}
现在,让我们来试(逝)一试(逝)
合理,恒河里~~~