题目:
现在小学的数学题目也不是那么好玩的。
看看这个寒假作业:
□ + □ = □
□ - □ = □
□ × □ = □
□ ÷ □ = □
每个方块代表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
就算两种解法。(加法,乘法交换律后算不同的方案)
你一共找到了多少种方案?
请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。
思路:这题很容易看出来是DFS 深度搜索,遍历每一种情况,并判断 是否符合题目要求,递归结束当12个格子填满
这题其实不算难,但是DFS要比较熟,这题自己卡了一下子,找了挺久的Bug 知道自己是多算了很多情况吗,但是愣是没找到错在哪,不过最终还是被找出来了,
想想,如果是现场赛的时候花这么多时间找Bug就完蛋了,说明自己对DFS还是不熟,多做多做!!!
下面看代码:
#include<iostream> #include<string.h> using namespace std; const int maxn=15+5; bool vis[maxn]; int a[maxn]; int ans=0; void dfs1(int sum,int pre,int now)//分别代表现在是第几个点 第一个框和第二个框的值分别是多少 { if(sum==12)//12个格子填满 递归结束 { ans++; for(int i=1;i<=12;i++) cout<<a[i]<<" "; cout<<endl; //cout<<ans<<endl; return ; } if(pre!=0&&now!=0)//两个格子都填满了 代表第三个格子已经确定了 { if(sum==2)//这里我默认的顺序是+ - * / { int z=pre+now; if(z<=13&&z>=1&&(!vis[z])) { vis[z]=true; a[1]=pre; a[2]=now; a[3]=z; //cout<<pre<<"+"<<now<<"="<<z<<endl; dfs1(sum+1,0,0); vis[z]=false; } else return ; } else if(sum==5) { int z=pre-now; if(z<=13&&z>=1&&(!vis[z])) { vis[z]=true; a[4]=pre; a[5]=now; a[6]=z; //cout<<pre<<"-"<<now<<"="<<z<<endl; dfs1(sum+1,0,0); vis[z]=false; } else return ; } else if(sum==8) { int z=pre*now; if(z<=13&&z>=1&&(!vis[z])) { vis[z]=true; a[7]=pre; a[8]=now; a[9]=z; //cout<<pre<<"*"<<now<<"="<<z<<endl; dfs1(sum+1,0,0); vis[z]=false; } else return ; } else if(sum==11) { if(pre%now==0) { int z=pre/now; if(z<=13&&z>=1&&(!vis[z])) { vis[z]=true; a[10]=pre; a[11]=now; a[12]=z; //cout<<pre<<"/"<<now<<"="<<z<<endl; dfs1(sum+1,0,0); vis[z]=false; } else return ; } else return ; } return ; } for(int i=1;i<=13;i++)//遍历每一个值 { if(!vis[i]) { vis[i]=true; if(pre==0) dfs1(sum+1,i,now); else if(now==0) dfs1(sum+1,pre,i);// !!!!我就是这里错了 写了两个if 改为else if就对了 /* 因为两个if的话 比如前面格子取4 递归下去后面格子取5 那么就是(4,5) 同时执行下面的if 后面的格子取4 前面的格子取5 那么就是(5,4) 前面格子取5 递归下去后面格子取4 那么就是(5,4) 同时执行下面的if 后面的格子取5 递归下去前面格子取4 那么就是(4,5) 是不是重复了 */ vis[i]=false; } } } int main() { memset(vis,false,sizeof(vis)); dfs1(0,0,0); cout<<ans<<endl; return 0; }