寒假作业
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
(如果显示不出来,可以参见【图1.jpg】)
每个方块代表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
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:其实也是全排列问题,把12个格子看成一维数组,然后填充,最后判断。值得注意的是13!很大,直接跑大约需要一分钟左右,这是填空题所以没什么事。但是我们可以添加几个优化。第22行加的语言可以排除很多无用的排列,大大的提高了效率。
解析
C++题解
#include <bits/stdc++.h>
using namespace std;
int a[13] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
int Ans;
bool check() {
if(a[9]%a[10] != 0) return false; // 不能整除
if(a[0]+a[1] != a[2]) return false; // + - * /
if(a[3]-a[4] != a[5]) return false;
if(a[6]*a[7] != a[8]) return false;
if(a[9]/a[10] != a[11]) return false;
return true;
}
void dfs(int x) {
if(x == 13) { // 填完了
if(check()) Ans++;
}
for(int i=x; i<13; ++i) {
swap(a[x], a[i]);
// 剪枝 不满足加法或减法 的跳过
// 因为加减法所需数字在前面 这样就减少了许多无用的 计算
if((x==2&&a[0]+a[1]!=a[2]) || (x==5&&a[3]-a[4]!=a[5])) {
swap(a[x], a[i]);
continue;
}
dfs(x+1);
swap(a[x], a[i]);
}
}
int main() {
dfs(0);
cout << Ans << endl;
return 0;
}
Java题解
public class _06寒假作业 {
public static void main(String[] args) {
dfs(0);
System.out.println(ans);
}
static int[] a = new int[] {1,2,3,4,5,6,7,8,9,10,11,12,13};
static int ans=0;
static void dfs(int m) {
if(m>=13) {//+ - * /
if(a[0]+a[1]==a[2] && a[3]-a[4]==a[5] && a[6]*a[7]==a[8] && a[9]/a[10]==a[11] && a[9]%a[10]==0) {
if(ans<10) {//11/2==5
System.out.println(a[0]+"+"+a[1]+"=="+a[2]);
System.out.println(a[3]+"-"+a[4]+"=="+a[5]);
System.out.println(a[6]+"*"+a[7]+"=="+a[8]);
System.out.println(a[9]+"/"+a[10]+"=="+a[11]);
System.out.println();
}
ans++;
}
return;
}
if(m>=3 && a[0]+a[1]!=a[2])//剪枝,2^13跑不出来
return;
if(m>=6 && a[3]-a[4]!=a[5])//这个剪不剪都行反正跑出来了
return;
for(int i=m;i<13;i++) {
swap(m,i);
dfs(m+1);
swap(m,i);
}
}
static void swap(int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
答案 64