C语言算法解决 123456789=100

使用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;
}

在这里插入图片描述

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值