凑算式(全排列dfs)

凑算式

    B      DEF
A +---- + ------- = 10
    C      GHI

(如果显示有问题,可以参见【图1.jpg】)

这个算式中AI代表19的数字,不同的字母代表不同的数字。

比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。

这个算式一共有多少种解法?
29
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
在这里插入图片描述

解题思路1:利用next_permutation(a,a+n)函数
注意分数相加减 数组要定义为double类型的, 下面的和也要是double类型的 包括10;
关于next_permutation()函数的使用 下面给出讲解

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
    int a[4]={1,2,3,4};
    do{
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;
    }while(next_permutation(a,a+4));
    system("pause");
    return 0;
}

即求括号中内容的下一个排列。如:a[4]={1,2,3,4}.next_permutation(a,a+4) 即为1,2,4,3.
函数原型:
若为4,3,2,1.next_permutation的返回值即为false,因为没有下一个排列。但是经过一次函数调用之后会变为1,2,3,4.
与之相对的还有一个函数为prev_permutation() 顾名思义,该函数为求上一个排列。
百度百科中的解释如下:
next_permutation函数将按字母表顺序生成给定序列的下一个较大的排列,直到整个序列为降序为止。prev_permutation函数与之相反,是生成给定序列的上一个较小的排列。二者原理相同,仅遍例顺序相反
问题:如何求一个数组的下一个排列?
假设该数组为3 6 4 2.下一个排列应为 4 2 3 6.
过程:对于一个任意序列,最小的排列是增序,最大的为减序。
从最后一位向前看,首先得到的是2,单纯的一个数不需要进行交换。
然后得到的是 4 2,4大于2,在这个子序列中已经为最大序列,无法排出更大的序列了。
然后得到的是 6 4 2,原理同上。
之后得到的是 3 6 4 2,此时由于3小于6且小于4,而 3 6 4 2的下一个排列应为比3 6 4 2这个排列大的排列中最小的那个,所以3应该和4进行交换,此时该排列变为 4 6 3 2.此时4位于首端,所以之后的序列应为最小序列,即 2 3 6.综上,最终结果应为 4 2 3 6.

#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
double a[10] = {1,2,3,4,5,6,7,8,9};
int ans = 0;
int main(){
	while(next_permutation(a,a + 9)){
		double sum = a[0] + (a[1] / a[2]) + (a[3] *100 + a[4] * 10 + a[5]) / (a[6] * 100 + a[7] * 10 + a[8]);
		if(sum == 10.0){
			ans++;
		} 	
	}
	cout << ans;
	return 0;
}

解题思路2:dfs递归搜索
注意分数相加减 数组要定义为double类型的, 下面的和也要是double类型的 包括10;
或者在分子后面 * 1.0 表示转换为double类型的数字

#include <iostream>
using namespace std;
double a[9] = {0};
int ans = 0;
bool judge(double a[]){
	double sum = a[0] + (a[1] * 1.0 / a[2]) + (a[3] *100 + a[4] * 10 + a[5]) * 1.0/ (a[6] * 100 + a[7] * 10 + a[8]);
	if(sum == 10.0){
		return true;
	} 
	return false;
}
bool check(int num){
	for(int i = num - 1;i >= 0;i--){
		if(a[i] == a[num]){//注意判断重复的条件
			return false;
		}
	}
	return true;
}
void dfs(int x){
	if(x > 8){
		if(judge(a)){
			ans++;
		}
		return;
	}
	for(int  i = 1;i < 10;i++){
		a[x] = i;
		if(check(x)){//注意检查的是参数的值 不是循环i的值
			dfs(x + 1);	
		}
	}
}
int main(){
	dfs(0);
	cout << ans;
	return 0;
} 

解题思路3:暴力

因为是分数当中涉及到除法 尽量不要用除法,因为里面涉及到精度的问题,我试了一次 出错了 答案不对 (当时没有考虑到int 和double 类型的问题)
可以使用下面的方法 通分过后比较
也可以使用下面的方式 进行转换为double类型的

if(a + ((b * 1.0) / c) + (d * 100 + e * 10 + f) * 1.0 /(g * 100 + h * 10 + j) == 10){
				ans += 1;
 } 
#include<iostream>
#include <algorithm>
using namespace std;
int main(){
	int ans = 0;
	int a,b,c,d,e,f,g,h,j;
	for(int a = 1;a <= 9;a++){
		for(int b = 1;b <= 9;b++){
			if(a == b){
				continue;
			}
			for(int c = 1;c <= 9;c++){
				if(a == c || b == c){
					continue;
				}
				for(int d = 1;d <= 9;d++){
					if(a == d || b == d || c == d){
						continue;
					}
					for(int e = 1;e <= 9;e++){
						if(a == e || b == e || c == e || d == e){
							continue;
						}
						for(int f = 1;f <= 9;f++){
							if(a == f || b == f || c == f || d == f || e == f){
								continue;
							}
							for(int g = 1;g <= 9;g++){
								if(a == g || b == g || c == g || d == g || e == g || f == g){
									continue;
								}
								for(int h = 1;h <= 9;h++){
									if(a == h || b == h || c == h || d == h || e == h || f == h || g == h){
										continue;
									}
									for(int j = 1;j <= 9;j++){
										if(a == j || b == j || c == j || d == j || e == j || f == j || g == j || h == j ){
											continue;
										}
										/*if(a + ((b * 1.0) / c) + (d * 100 + e * 10 + f) * 1.0 /(g * 100 + h * 10 + j) == 10){
												ans += 1;
					 					} */
										int t1 = a * c * ( 100 * g + 10 * h + j ); 
                                        int t2 = b * (100 * g + 10 * h + j); 
                                        int t3 = c * (100 * d + 10 * e + f); 
                                        int t4 = 10 * c * (100 * g + 10 * h + j); 
                                        if( t1 + t2 + t3 == t4)ans++;
									}
								}
							}
						}
					}
				}
			}
		}
	}
	cout << ans;
	return 0;
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值