使用C语言算法解决 12345789=100
无意中看到这道题,应该是道小学奥数,我在尝试手算了几次没算出来后,准备使用c语言算法解决。
题目描述:123456789=100,在123456789顺序不变的情况下,插入n个加号或者减号,使得等式成立。
例如: 12+34+56+7+8+9=126
一开始我的想法是在数字中按排列组合的顺序插入正负号,这样的做法用程序难以表达,而且插入操作实现起来不容易。
首先考虑最简单的情况,123456789如果分成9个数字,那么就是1、2、3、4、5、6、7、8、9。进一步,如果将123456789分成8个数字有多少种情况呢,如果我们将前两个数字划分成一个数字就是12、3、4、5、6、7、8、9.
我们可以发现,如果将前两个数字1、2分成一个数字之后,我们就剩下了3、4、5、6、7、8、9这七个数字,算上刚刚分出来的12,一共是八个数字。
也就是说,当我们分出来前面的12之后,后面的3、4、5、6、7、8、9刚好组成了剩下的七个数字,这不是与最简单的情况相似吗?
我们不妨将9个数字分成8个数的任务记为T(8,9),则将R个数字分成N个数的任务就记为T(N,R)。R表示剩余的数字,N表示需要分成N个数字。
对于每个任务我们只考虑第一个数字至多可以与后面多少个数字结合,对与任务T(8,9)来说,第一个数字最多可以与后面1个数字结合,此时任务变成了T(7,7),对于任务T(7,7)来说其第一个数字不能与任何数字结合,而且其子任务也是如此。当第一个数字不与其他数字结合时,后面的任务就变成了T(7,8),他与T(8,9)相似,但规模更小。
进一步对于将9个数字分成7个数的任务,T(7,9),其第一个数字可以选择:1.不与其他数结合、2.与后面一个数结合、3.与后面两个数结合。
不管其第一个数字与几个数字结合,我们都将生成一个数,但第一个数字结合的数字越多,剩余的数字就越少。
对于一般的情况T(N,R),需要将剩余的R个数字分成N个数的任务,我们可以知道第一个数字至多与后面R-N个数字结合,(一共R-N+1个数字组成了一个数,这样剩下的N-1个数字刚好组成N-1个数)。
#include <iostream>
#include <cstdio>
using namespace std;
int nums[9], now_num = 1;
int index = 0;
int flags[9];//保存符号
// 递归计算选出的n个数的 + - 排列组合求和结果
int calulate(int i,int sum)
{
if (i == index+1) {
if (sum == 100) {
for (int j = 0; j <= index; j++) {
printf("%d", nums[j]);
if (j != index)
if (flags[j+1]) printf("-");
else printf("+");
}
printf("=%d\n", sum);
}
return 0;
}
if (i == 0) {
calulate(i + 1, nums[i]);
return 0;
}
flags[i] = 0;//0是+
calulate(i + 1, sum + nums[i]);
flags[i] = 1;//1是-
calulate(i + 1, sum - nums[i]);
return 0;
}
// n是总共要分成n个数字 r是剩余的数字
int generate_num(int n,int r)
{
//结束递归 n=1时 剩下的所有数字组成一个
if (n == 1)
{
for (int i = 0; i <= r - n; i++) {
nums[index] = nums[index] * 10 + now_num++;
}
calulate(0, 0);
nums[index] = 0;
now_num -= r - n + 1;
return 0;
}
//至多可以与其后面R-N个数字结合
for (int i = 0; i <= r-n; i++)
{
//计算结合后的数字
for (int j = 0; j < i + 1; j++) {
nums[index] = nums[index]*10+ now_num++;
}
index++;//数字个数加一
generate_num(n - 1, r - i - 1);
//回溯
index--;
nums[index] = 0;
now_num -= i + 1;
}
return 0;
}
int main()
{
for (int i = 9; i >= 2; i--) {
printf("i=%d\n", i);
//计算将9个数字分成i个数的结果
generate_num(i, 9);
}
return 0;
}