之前做过这道题,当时想的是爆搜的做法,今天发现其实可以用全排列做
题目
凑算式
B DEF
A + --- + ------- = 10
C GHI
(如果显示有问题,可以参见【图1.jpg】)
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。
全排列的解法
每一次找到一个可能的结果就直接判断是否和等于10就行
我们通过内置的全排列函数next_permutation
去生成不同的可行解,每一次去验证是否正确
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int a[]={1,2,3,4,5,6,7,8,9};
int ans=0;
bool check(){
int x = a[3] * 100 + a[4] * 10 + a[5];
int y = a[6] * 100 + a[7] * 10 + a[8];
if(a[0] + a[1]/a[2] + x/y == 10)
return true;
return false;
}
//递归回溯生成全排列,适用于无重复元素的情况
int main(int argc, const char * argv[]) {
do{
if(check())
ans++;
}while(next_permutation(a,a+9));
cout<<ans<<endl;
return 0;
}
结果竟然是:29807
不对哇,为什么呢?
发现有的时候B/C+DEF/GHI不是整数,需要先通分再求和。
a[0] + (a[1] * y + a[2] * x) / (y * a[2]) == 10
得出结果竟然是:35721
发现还是不行??为什么结果越来越大了???
这样计算,整数和整数加和会自动舍弃小数,所以需要确保后面两项的和一定是整数:
if((a[1] * y + a[2] * x) % (y * a[2])==0 && a[0] + (a[1] * y + a[2] * x) / (y * a[2]) == 10)
这样才是正确的结果
手动全排列
就是从第一个位置开始找,跟全排列的思想一样
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int a[]={1,2,3,4,5,6,7,8,9};
int ans;
bool check(){
int x = a[3] * 100 + a[4] * 10 + a[5];
int y = a[6] * 100 + a[7] * 10 + a[8];
if((a[1] * y + a[2] * x) % (y * a[2])==0 && a[0] + (a[1] * y + a[2] * x) / (y * a[2]) == 10)
return true;
return false;
}
//递归回溯生成全排列,适用于无重复元素的情况
void f(int k) {
if(k==9){//一种排列已经生产
if(check())
ans++;
}
// 从k往后的每个数字都可以放在k位
for (int i = k; i < 9; ++i) {
{int t=a[i];a[i]=a[k];a[k]=t;}
f(k+1);//递归
{int t=a[i];a[i]=a[k];a[k]=t;}//回溯
}
}
int main(int argc, const char * argv[]) {
f(0);
cout<<ans<<endl;
return 0;
}
第七届蓝桥杯省赛第三题,难度因该还好,很经典的一道题