埃及分数(迭代加深搜)
2015-07-29 00:14
162 查看
迭代加深搜索,实质上是限定下界的深度优先搜索。即首先允许深度优先搜索K层,若没有发现可行解,再将K+1后
重复以上步骤搜索,直到搜索到可行解。
在迭代加深搜索的算法中,连续的深度优先搜索被引入,每一个深度约束逐次加1,直到搜索到目标为止。这样可以
看出重复搜索了好多。但是它的好处在于:
1.空间开销小 每个深度下实际上是一个深度优先搜索,不过深度有限制,而DFS的空间消耗小是众所周知的。
2.利于深度剪枝
3.时间效率不低
虽然重复搜索,但是大家不难理解,前一次搜索跟后一次相不是微不足到的。
我们可以看出,迭代加深搜索算法就是仿广度优先搜索的深度优先搜索。既能满足深度优先搜索的线性存储要求,又能保证发现一个最小深度的目标结点。
从实际应用来看,迭代加深搜索的效果比较好,并不比广度优先搜索慢很多,但是空间复杂度却与深度优先搜索相同,比广度优先搜索小很多。
使用搜索算法的时候,选择正确的搜索方式很重要。当有一类问题需要做广度优先搜索,但却没有足够的空间,而时间却很充裕,碰到这类问题,我们可以选择迭代加深搜索算法。
埃及分数:
给你个真分数,你需要将其化简为最少的若干特殊真分数之和,你要输出这个序列(序列按递增序)。如果有不同的方案,则分数个数相同的情况下使最大的分母最小。若还相同,则使次大的分母最大……以此类推。如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
题目分析:
对于任意给定的a,b,1/k<=a/b<=1/p成立(这比较抽象,不过幸好这不是重点),也就是说,为了使程序具有更高的剪枝效率,我们需要找到所谓的上界与下界。
对于上界的寻找,我们可以极端化考虑。对于任意满足条件的a,b,都有a/b<INF/b,所以我们规定上界为INF/b,这个想法很单纯,切勿多想。
对于下界的寻找:a/b=1/(b/a),所以如果规定int t=b/a,那么t<=b/a恒成立,所以可以说1/t>=1/(b/a)恒成立。又在递归迭代搜索中,dep表示当前搜索限制深度,k表示当前搜索深度,则当前分数就一定是由(dep-k+1)个特殊真分数的和,每个真分数最大就是1/[(b/a)*(dep-k+1)],所以对原式进行放缩,有:
a/b=1/(b/a)=(dep-k+1)*1/[(b/a)*(dep-k+1)]<=1/t,即a/b>=t,故可知,t为理论下界。
转载出处:http://blog.csdn.net/acdreamers/article/details/18226915
转载出处:http://m.blog.csdn.net/blog/u012905448/39162723
重复以上步骤搜索,直到搜索到可行解。
在迭代加深搜索的算法中,连续的深度优先搜索被引入,每一个深度约束逐次加1,直到搜索到目标为止。这样可以
看出重复搜索了好多。但是它的好处在于:
1.空间开销小 每个深度下实际上是一个深度优先搜索,不过深度有限制,而DFS的空间消耗小是众所周知的。
2.利于深度剪枝
3.时间效率不低
虽然重复搜索,但是大家不难理解,前一次搜索跟后一次相不是微不足到的。
我们可以看出,迭代加深搜索算法就是仿广度优先搜索的深度优先搜索。既能满足深度优先搜索的线性存储要求,又能保证发现一个最小深度的目标结点。
从实际应用来看,迭代加深搜索的效果比较好,并不比广度优先搜索慢很多,但是空间复杂度却与深度优先搜索相同,比广度优先搜索小很多。
使用搜索算法的时候,选择正确的搜索方式很重要。当有一类问题需要做广度优先搜索,但却没有足够的空间,而时间却很充裕,碰到这类问题,我们可以选择迭代加深搜索算法。
埃及分数:
给你个真分数,你需要将其化简为最少的若干特殊真分数之和,你要输出这个序列(序列按递增序)。如果有不同的方案,则分数个数相同的情况下使最大的分母最小。若还相同,则使次大的分母最大……以此类推。如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
题目分析:
对于任意给定的a,b,1/k<=a/b<=1/p成立(这比较抽象,不过幸好这不是重点),也就是说,为了使程序具有更高的剪枝效率,我们需要找到所谓的上界与下界。
对于上界的寻找,我们可以极端化考虑。对于任意满足条件的a,b,都有a/b<INF/b,所以我们规定上界为INF/b,这个想法很单纯,切勿多想。
对于下界的寻找:a/b=1/(b/a),所以如果规定int t=b/a,那么t<=b/a恒成立,所以可以说1/t>=1/(b/a)恒成立。又在递归迭代搜索中,dep表示当前搜索限制深度,k表示当前搜索深度,则当前分数就一定是由(dep-k+1)个特殊真分数的和,每个真分数最大就是1/[(b/a)*(dep-k+1)],所以对原式进行放缩,有:
a/b=1/(b/a)=(dep-k+1)*1/[(b/a)*(dep-k+1)]<=1/t,即a/b>=t,故可知,t为理论下界。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; #define LL __int64; const int INF = ~0U>>1; //无穷大的表示法(~0U的意思是先把0强制转化为unsigned类型,再各位取反),这样得到的就是最大值。 const int N = 1000; //最大所需深度 int dep,flag; //当前深度限制变量 和 成功标记变量 int ans ,d ; //ans为结果数组,d为深度结果数组 //最大公约数算法 int gcd(int a,int b) {return b ?gcd(b,a%b):a;} //DFS基本主模块 void dfs(int a,int b,int k){ //k为当前深度 if(k == dep + 1) return; //深度优先出口 if(b % a == 0&& b / a > d[k-1]){ //这种情况是找到了解的情况,其实就是a==1的情况,这种情况肯定有解。 d[k] = b / a; if(!flag || d[k] < ans[k]) memcpy(ans,d,sizeof(d)); flag = 1; return; } int s = b / a; //分母的理论下界寻找 if(s <= d[k-1]) s = d[k-1] + 1; //确保下界是正确的 int t = (dep - k + 1) * b /a; //分母的理论上界寻找 if(t > INF / b) t = INF / b; //确保上界是正确的 if(flag && t >= ans[dep]) t = ans[dep] - 1; //如果上界超过前层递归的范围就把上界进行缩短 for(int i=s;i<=t;i++){ d[k] = i; //表示k这一层目前所到的最大深度 int m = gcd(i*a - b,b*i); //最大公约数 dfs((i*a-b)/m,b*i/m,k+1); //继续DFS } } void Work(int a,int b) { d[0] = 1; //d[0]初始化 flag = 0; //默认找不到解 for(dep=1;dep <= N;dep++){ //深度加深 dfs(a,b,1); //进行迭代递归搜索 if(flag){ //如果找到解的话 printf("1/%d",ans[1]); //输出解 for(int i=2;i<=dep;i++) printf("+1/%d",ans[i]); cout<<endl; break; //不继续进行加深搜索 } } } int main() { int a,b; while(cin>>a>>b){ cout<<a<<"/"<<b<<"="; Work(a,b); } return 0; }</span>
转载出处:http://blog.csdn.net/acdreamers/article/details/18226915
转载出处:http://m.blog.csdn.net/blog/u012905448/39162723
相关文章推荐
- iis 更改asp.net 版本设置
- hdu 5124 lines(贪心)
- MFC程序打开文件对话框出错的问题解决
- 杭电1896 Stones
- python多线程
- 安装星际译王
- linux查看和关闭后台执行程序
- C++ Pragma 预处理指令
- 安装星际译王
- Hello Pythoner!
- 什么才是好的产品?
- ABaseApdater
- 【算法学习笔记】88.显式DFS SJTU OJ 2202. 梅西的过人
- 值得一看
- hdu 5123 who is the best?(水)
- [HDU:5316]Magician
- AngularJS开发指南
- CodeForces 18C - Stripe
- 浅谈Java多线程中的Thread.sleep()和wait()方法的区别
- hdu 5053 the Sum of Cube(水)