这天,还在读小学的白白在地上摆弄着火柴,你上前问道,白白说“这是老师布置的作业,给了我14根火柴,问我们可以摆成多少个加法式子。”
你哈哈大笑起来,为了让小屁孩刮目相看,你随手掏出笔记本电脑,啪啪啪地敲起来了。
小孩看到你一下摆出了"0+7=7"、"1+2=3"、"1+7=8"……,立马开心地叫你大哥!
小孩说班上每个同学的火柴数都不一样,你为了做孩子王,转身敲起了代码。
现在给定你n根火柴,火柴摆放位置与数字的关系如下图所示
请你找到所有满足A+B=C的等式,等式应满足以下四个条件:
- 如果A≠B,则认为A+B=C与B+A=C为不同的等式
- 0 ≤ A ≤ B ≤ C ≤ 10000,且A、B、C除非为0,否则最高位不能是0
- 所有火柴必须全部用上
- 加号和等号各自需要两根火柴棒。
如果没有满足的等式,请输出“No Solution!”
输入格式:
第一行给定正整数n(n ≤ 24)
输出格式:
每行输出A+B=C的式子,如果有多条解决方案,请依次按A、B、C的大小非降序排列
如果没有满足的等式则输出“No Solution!”
输入样例:
16
输出样例:
0+7=7
1+2=3
1+7=8
2+1=3
3+4=7
4+3=7
7+0=7
7+1=8
7+7=14
输入样例:
11
输出样例:
No Solution!
思路:
题目中限制了A、B、C的范围,因此利用暴力破解:依次令A循环从0~10000,令B循环从0~10000,A+B即为C的取值,检测一下火柴数量是否合格即可。
小技巧:
- 为了加快代码的运行速度,可以新建一个数组来存储每一个数字所需要耗费的火柴数量。初始我们知道前10个数字的消耗量,我们只需要从10开始迭代,例如69这个数字,需要耗费6和9所对应的火柴数量,再比如123这个数字,需要耗费12和3所对应火柴数量,而12需要耗费1和2这两个数字的火柴数量。(有一点动态规划的味道在里面)
- 依次迭代10000*10000也是很大的开销,为了避免超时,如果迭代到A的火柴数量已经超过了24-4-4(运算符需要耗费4根,其他两个数字至少需要耗费4根,也就是B=C=1时)根,那么就不需要再依次迭代每一个B的取值了,这样极大地优化了时间开销。
参考代码:
#include<iostream>
using namespace std;
const int MAXSIZE = 10001;
int main() {
int consume[MAXSIZE] = { 6,2,5,5,4,5,6,3,7,6 };
int n;
scanf("%d", &n);
// 得到每一个数字所需要的火柴数量
for (int i = 10; i < MAXSIZE; i++) {
consume[i] = consume[i % 10] + consume[i / 10];
}
bool haveSolutions = false;
for (int A = 0; A <= MAXSIZE; A++) {
if (consume[A] > n - 8) continue; // 时间优化
for (int B = 0; B <= MAXSIZE; B++) {
int C = A + B;
if (C <= MAXSIZE && consume[A] + consume[B] + consume[C] == n - 4) {
printf("%d+%d=%d\n", A, B, C);
haveSolutions = true;
}
}
}
if (!haveSolutions) {
cout << "No Solution!" << endl;
}
return 0;
}