1285: [蓝桥杯2016初赛]寒假作业
题目描述
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
每个方块代表1~13中的某一个数字,但不能重复。
比如:
6 + 7 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
以及:
7 + 6 = 13
9 - 8 = 1
3 * 4 = 12
10 / 2 = 5
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
输出格式
请填写表示方案数目的整数。
#include
#define bool char
#define true 1
#define false 0
bool num[13];
int res=0;
int a[13]={1,2,3,4,5,6,7,8,9,10,11,12,13};
bool check()
{
if
( a[0]+a[1] == a[2] && a[3]-a[4] == a[5] && a[6]*a[7] == a[8] && a[11]*a[10] == a[9] )
{
return true;
}
return false;
}
void dfs(int u)
{
if(u==13)
{
if(check())
{
res++;
}
return;
}
int i;
for(i=0;i<13;i++)
{
if(num[i] == false)
{
num[i] = true;
a[u] = i+1;
dfs(u+1);
num[i] = false;
}
}
return;
}
int main()
{
dfs(0);
printf("%d",res);
return 0;
}
不知道哪出问题了,能帮忙找找错吗?
你这个思路本身没有什么问题,就是穷举法,会循环13!次,也就是62亿多次循环,非常耗时。
所以就是尽可能的提升效率。
这里提供个参考:
#include<stdio.h>
int res=0;
int a[13]={1,2,3,4,5,6,7,8,9,10,11,12,13};
// 该方法可以理解为,k位之前的数已经确定,计算k位开始的这满足的数量
void dfs(int k)
{
// 前3位确定后,如果不满足第一个等式则后面的不需要继续判断
if(k>=3){
if(a[0] + a[1] != a[2]) {
return ;
}
}
// 同理,前6位确定后。经过上面的判断,代表前三位一定满足第一个等式,那么第4-6位如果不满足第二个等式则后面的不需要继续判断,下面同理
if(k>=6){
if(a[3] - a[4] != a[5]) {
return ;
}
}
if(k>=9) {
if (a[6] * a[7] != a[8]) {
return;
}
}
// 所有位都确定且四个等式都满足的情况下,res加1代表符合条件
if(k>=12){
if(a[11]*a[10]==a[9]) {
res++;
return ;
}
}
// 前k位已经确认的情况下
for(int i=k;i<13;i++) {
// 通过下面的交换将第k+1位先确定一下(循环多次即尝试其所有可能性),然后递归执行dfs(k+1)
int t=a[i];a[i]=a[k];a[k]=t;
dfs(k+1);
// 进入下次循环前要将数组复原这样才能保证下次循环没有问题
t=a[i];a[i]=a[k];a[k]=t;
}
return;
}
int main()
{
dfs(0);
printf("%d",res);
return 0;
}