sicily1050-Numbers & Letters
2015-05-14 12:30
393 查看
一道经典的深搜题,以为自己可以轻松解决的,结果犯了很多细节上的错误,都记录下来作个警示吧。
题目大意是用+-*/任意组合5个数(每种符号使用次数不限,除法要求只能是整除,每个数字只能用一次,可以不用完全部数字),使得运算res为小于等于给定target的最大值
思路是穷举5个数的排列方式,挑选另一个数与它进行叠加(+-*/),
深搜进去变成4个数,再穷举4个数的排列方式……
深搜进去变成3个数……
直到最后只剩一个数,也就是运算结果
唉这学期太忙,化在算法课上的时间好少,题都不会刷了,要好好反思一下了。
犯错点用数字标记出来了。
①这个if必须放在最前面(否则若把第3个if提到首,若到level4时找到了答案,根本没对finalres赋值就return掉了),下面两个if的顺序无所谓,区别只在get没有而已,只是为了早一步结束不必要的搜索,但是并不影响结果
②当num[level]>target或是<0时不能return,因为有可能通过后面的运算再把数值拉回到范围之内,下方算a-b和b-a两种减法也是同理
③复制num数组方便传入,这种内存问题自己犯过好多次了,有强迫症希望能少用空间就少用空间,这种习惯挺好但是自己老是死在这上面,想对内存空间重复利用就必须要记得保护现场和恢复现场啊,像这一题用这种实现方法的话,这样大量开辟栈空间是不可避免的了
④题目中只允许整除,注意下面要是elseif,防止a==b的情况算两次
⑤虽然题目说target是在[0,1000],但是这句改成-1都WA,估计是有负数输入的,究竟是num[i]还是target就不得而知了
题目大意是用+-*/任意组合5个数(每种符号使用次数不限,除法要求只能是整除,每个数字只能用一次,可以不用完全部数字),使得运算res为小于等于给定target的最大值
思路是穷举5个数的排列方式,挑选另一个数与它进行叠加(+-*/),
深搜进去变成4个数,再穷举4个数的排列方式……
深搜进去变成3个数……
直到最后只剩一个数,也就是运算结果
唉这学期太忙,化在算法课上的时间好少,题都不会刷了,要好好反思一下了。
犯错点用数字标记出来了。
#include <iostream> #include <algorithm> using namespace std; int num[5]; int target; int finalres; bool get; void dfs(int* num, int level){ if (num[level] > finalres && num[level] <= target)//① finalres = num[level]; if (finalres == target){ get = true; return; } if (level == 4 || get)//② return; int tmp[5]; for (int i = level; i < 5; i++){ for (int j = i + 1; j < 5; j++){ int a = num[i], b = num[j], count = 4; for (int k = 4; k >= level; k--){//③ if (k == i || k == j) continue; tmp[count--] = num[k]; } tmp[level + 1] = a + b; dfs(tmp, level + 1); tmp[level + 1] = a - b; dfs(tmp, level + 1); tmp[level + 1] = b - a; dfs(tmp, level + 1); tmp[level + 1] = a * b; dfs(tmp, level + 1); if (a!= 0 && b != 0 && a % b == 0){//④ tmp[level + 1] = a / b; dfs(tmp, level + 1); } else if (a!= 0 && b != 0 && b % a == 0){ tmp[level + 1] = b / a; dfs(tmp, level + 1); } } } } int main(){ int N, T; cin >> N; while (N--){ for (int i = 0; i < 5; i++){ cin >> num[i]; } cin >> target; get = false; finalres = -2000000000;//⑤ dfs(num, 0); cout << finalres << endl; } return 0; }
①这个if必须放在最前面(否则若把第3个if提到首,若到level4时找到了答案,根本没对finalres赋值就return掉了),下面两个if的顺序无所谓,区别只在get没有而已,只是为了早一步结束不必要的搜索,但是并不影响结果
②当num[level]>target或是<0时不能return,因为有可能通过后面的运算再把数值拉回到范围之内,下方算a-b和b-a两种减法也是同理
③复制num数组方便传入,这种内存问题自己犯过好多次了,有强迫症希望能少用空间就少用空间,这种习惯挺好但是自己老是死在这上面,想对内存空间重复利用就必须要记得保护现场和恢复现场啊,像这一题用这种实现方法的话,这样大量开辟栈空间是不可避免的了
④题目中只允许整除,注意下面要是elseif,防止a==b的情况算两次
⑤虽然题目说target是在[0,1000],但是这句改成-1都WA,估计是有负数输入的,究竟是num[i]还是target就不得而知了
相关文章推荐
- sicily 1050. Numbers & Letters
- sicily1050 Numbers & Letters
- Sicily 1050. Numbers & Letters
- Sicily 1050. Numbers & Letters
- Sicily 1050. Numbers & Letters
- Sicily 1050. Numbers & Letters
- sicily 1050 Numbers & Letters
- Sicily 1050. Numbers & Letters
- sicily 1050 Numbers & Letters
- sicily 1050 Numbers & Letters
- sicily 1050. Numbers & Letters
- sicily 1050.Numbers & Letters
- [sicily online]1050. Numbers & Letters
- Sicily 1050 Numbers & Letters
- Sicily 1050 Numbers & Letters(DFS)
- 1050. Numbers & Letters
- sicily 1050 Numbers & Letters
- ZOJ&nbsp;1078&nbsp;Palindrom&nbsp;Numbers
- Sicily.1050. Numbers & Letters(DFS)
- sicily 1063. Who's the Boss