您的位置:首页 > 其它

22-小学生的数学题目?exm?

2018-02-28 01:35 260 查看

一、具体描述

寒假作业
现在小学的数学题目也不是那么好玩的。 
看看这个寒假作业:
□ + □ = □ 
□ - □ = □ 
□ × □ = □ 
□ ÷ □ = □
(如果显示不出来,可以参见【图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
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
可以用深度优先遍历和暴力破解。
**暴力思路**
更详细地讲,为方便说明,具体假设及思路流程如下:
a1+a2=x1;
a3-a4=x2;
a5*a6=x3;
a7/a8=x4;
a1,a2,a3...a8;x1,x2,x3,x4的范围为[1,13],且均为整数,有且仅出现过一次。
我们想用暴力,那么就得尽可能的降低时间复杂度以达到最佳效果。既然这样,我们发现,x1,x2,x3,x4是受到a1,a2...a8这8个数影响的,所以我们只需要遍历8个数即可。对于x1,x2,x3,x4,我们可以根据8个数的值来确定是否存在。
那么什么是存在问题呢?其实等同可以说符合问题,我们一旦确认一个数的值(比如确定第一个数a1),就将它标记一次,以说明它不能在后续遍历(比如遍历a2等)的时候用到了。那么,我们开始遍历吧。
1. 确定a1。
标记 vis[a1]=1 。
2. 确定a2。
(1) 判断 a1+a2>13 ? (如果>13,即x1>13,遍历下一个a2) 并且 vis[a2]==1 ? (如果已经标记了a2,遍历下一个a2)。
(2) 如果不符合(1),则说明a2是可能符合的,继续标记 vis[a2]=1,vis[a1+a2]=1(vis[x1]=1),即这时的a1,a2,x1均被标记了,下面就不能再出现了。
3. 确定a3。
只要判断 a3 是否被标记即可( vis[a3]==1 ? ),如果没有,记下a3( vis[a3]=1),继续遍历下面的数。
4. 确定a4。
(1) a3-a4<0 ? a3-a4必须大于0。
(2) a3-a4>14 ? a3-a4必须小于14。
(3) vis[a4]==1 ? vis[a3-a4]==1 (vis[x2]==1)? 我们当然知道,这是不能被标记的。
(4) 这是最重要的一点,一定要确定 a3-a4 是否等于 a4;因为如果(1)(2)(3)均不符合,就说明a4还没有被标记;如果 a3-a4继续等于a4,那么这个条件被隐性符合了,然而这是不对的!
(5) 如果(1)(2)(3)(4)均不符合,那么我们可以标记vis[a4]=1,vis[a3-a4]=1(vis[x2]=1)了。
5. 确定a5。
只要判断 a5 是否被标记即可( vis[a5]==1 ? ),如果没有,记下a5( vis[a5]=1),继续遍历下面的数。

6. 确定a6。
(1) a5*a6 > 13 ?
(2) vis[a6]==1 ? vis[a5*a6]==1(vis[x3]==1) ?
(3) 重要的一点,同4(4),a6==a5*a6 ?
(4) 如果(1)(2)(3)均不符合,那么我们可以标记vis[a6]=1,vis[a5*a6]=1(vis[x3]=1)了。
7. 确定a7。
只要判断 a7 是否被标记即可( vis[a7]==1 ? ),如果没有,记下a5( vis[a7]=1),继续遍历下面的数。

8. 确定a8。
(1) a7<a8 ? 如果符合,那么x4不为整数。
(2) a7%a8 != 0 ? 这句话说明a7一定要整除a8。
(3) vis[a8]==1 ? vis[a7/a8]==1(vis[x4]==1) ?
(4) 重要的一点,同4(4),6(3),a8==a7/a8 ?
(5) 如果(1)(2)(3)(4)均不符合,那么不用标记a8,我们可以记录生成一种情况了。
!!!注意找到一种答案后,需要去除标记,以达到循环,否则会漏很多解,甚至无解!
**DFS思路**
按部就班,和暴力差不多。

二、代码解析

(暴力)

//
//  main.cpp
//  xiaoxuesheng
//
//  Created by apple on 2018/2/28.
//  Copyright © 2018年 apple. All rights reserved.
//
#include <iostream>
using namespace std;
int main(){
//define
int a1, a2, a3, a4, a5, a6, a7, a8;//representative parameters
int vis[14] = {0};//if tag?
int tot = 0;//record the number of the proper approaches.
//violence
//a1
for (a1 = 1; a1 <= 13; ++a1) {
vis[a1] = 1;//tag
//a2
for (a2 = 1; a2 <= 13; ++a2) {//----------------->a1+a2=?
//Judge if a1+a2>13 ? yes,pass a2,continue
if (a1 + a2 > 13 || vis[a2]) {
continue;
}
//if not,tag vis[a1+a2]
vis[a2] = 1;
vis[a1 + a2] = 1;
//a3,is the same as a1
for (a3 = 1; a3 <= 13; ++a3) {
//if taged,continue
if (vis[a3]) {
continue;
}
//if not,tag
vis[a3] = 1;
//a4
for (a4 = 1; a4 <= 13; ++a4) {//------------------->a3-a4=?
//Judge if yes,continue
if (a3 - a4 < 0 || a3 - a4 > 14 || vis[a4] || vis[a3 - a4] || a4 == a3 - a4) {
continue;
}
//if not,tag,the same as a1+a2
vis[a4] = 1;
vis[a3 - a4] = 1;
//a5,the same as a1 and a3
for (a5 = 1; a5 <= 13; ++a5) {
//if taged,continue
if (vis[a5]) {
continue;
}
//if not,tag
vis[a5] = 1;
//a6
for (a6 = 1; a6 <= 13; ++a6) {//------------>a5*a6=?
//Judge,if yes,continue
if (a5 * a6 > 13 || vis[a6] || vis[a5 * a6] || a6 == a5 * a6) {
continue;
}
//if not,tag
vis[a6] = 1;
vis[a5 * a6] = 1;
//a7,the same as a1,a3,a5
for (a7 = 1; a7 <= 13; ++a7) {
if (vis[a7]) {
continue;
}
//if not taged,tag
vis[a7] = 1;
//a8
for (a8 = 1; a8 <= 13; ++a8) {//------------->a7/a8=?
//Judge,if yes,continue
if (vis[a8] || a7 < a8 || a7 % a8 != 0 || vis[a7 / a8] || a8 == a7 / a8) {
continue;
}
//if not ,tot+1
tot++;
}
//reduction
vis[a7] = 0;
}
//reduction
vis[a6] = 0;
vis[a5 * a6] = 0;
}
//reduction
vis[a5] = 0;
}
//reduction
vis[a4] = 0;
vis[a3 - a4] = 0;
}
//reduction
vis[a3] = 0;
}
//reduction
vis[a2] = 0;
vis[a1 + a2] = 0;
}
//reduction
vis[a1] = 0;
}
cout<<tot<<endl;
return 0;
}

(深度优先遍历呢?)

这里先只给代码。基本思路差不多。#include <stdio.h>
#define _MAX 13

int ans = 0;
int num[_MAX] = {0};
int visited[_MAX] = {0};

int test(int n)
{
if (n == 2)
{
if (num[0] + num[1] == num[2])
{
return 1;
}
}
else if (n == 5)
{
if (num[3] - num[4] == num[5])
{
return 1;
}
}
e
4000
lse if (n == 8)
{
if (num[6] * num[7] == num[8])
{
return 1;
}
}
else if (n == 11)
{
if (num[10] * num[11] == num[9])
{
ans++;
return 1;
}
}
else
{
return 1;
}
return 0;
}

void dfs(int n)
{
int i = 0;
if (n >= _MAX)
{
return ;
}
for (; i < _MAX; i++)
{
if (!visited[i])
{
visited[i] = 1;
num
= i + 1;
if (!test(n)) //如果不符合规则,则撤销这个分支
{
visited[i] = 0;
continue;
}
dfs(n + 1);
visited[i] = 0;
}
}
return ;
}

int main()
{
dfs(0);
printf("%d\n", ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: