Codevs 1288 埃及分数 【IDA*】
2016-07-25 22:13
375 查看
题目链接
今天发现了Codevs这个OJ的存在,给人耳目一新的感觉,然后就A了这个题。然而居然做的第一题的测试数据就有问题(有争议)……
题中最优解首先是长度最短,这就给了IDA*用武之处,不断地求当前深度的最优解,若当前深度存在可行解,则当前深度的最优解就是最终的最优解。DFS时,每一层可选的分数,就是比之前加起来离目标分数的剩余量还小的埃及分数。枚举时,若接下来即使每一层都选择当前这个分数,仍然无法达到目标分数,则剪枝。所以启发函数g(i)=ab⋅i+1(a/b是剩余量,i是当前选择的埃及分数的分母),也即d+g(i)>=maxd时剪枝
题意
非常出名而基础的一道题,也是lrj紫书上讲解IDA*的例题。今天发现了Codevs这个OJ的存在,给人耳目一新的感觉,然后就A了这个题。然而居然做的第一题的测试数据就有问题(有争议)……
分析
首先看这个搜索的决策,既无法确定搜索深度的下界(可以有无限个分数相加),也无法确定宽度的下界(分数可以无限小),因此考虑使用IDA*题中最优解首先是长度最短,这就给了IDA*用武之处,不断地求当前深度的最优解,若当前深度存在可行解,则当前深度的最优解就是最终的最优解。DFS时,每一层可选的分数,就是比之前加起来离目标分数的剩余量还小的埃及分数。枚举时,若接下来即使每一层都选择当前这个分数,仍然无法达到目标分数,则剪枝。所以启发函数g(i)=ab⋅i+1(a/b是剩余量,i是当前选择的埃及分数的分母),也即d+g(i)>=maxd时剪枝
可能正确的代码
(数据有争议,若要强行过这个题,加上三个数据的特判)#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cctype> #include <cstdlib> #include <cstring> #include <vector> #include <set> #include <string> #include <map> #include <queue> #include <deque> #include <list> #include <sstream> #include <stack> using namespace std; #define cls(x) memset(x,0,sizeof x) #define inf(x) memset(x,0x3f,sizeof x) #define neg(x) memset(x,-1,sizeof x) #define ninf(x) memset(x,0xc0,sizeof x) #define st0(x) memset(x,false,sizeof x) #define st1(x) memset(x,true,sizeof x) #define INF 0x3f3f3f3f #define lowbit(x) x&(-x) #define bug cout<<"here"<<endl; //#define debug int maxd; long long res[10000]; long long v[10000]; bool better(int d) { for(int i=d;i>=0;--i) { if(v[i]!=res[i]) return res[i]==-1||v[i]<res[i]; } return false; } long long gcd(long long a,long long b) { if(b==0) return a; return gcd(b,a%b); } long long get_first(long long a,long long b) { long long g=gcd(b,a); a/ cae6 =g;b/=g; if(b%a==0) return b/a; return b/a+1; } bool DFS(int d,long long from,long long a,long long b) { if(d==maxd) { if(b%a)return false; v[d]=b/a; if(better(d)) memcpy(res,v,sizeof(long long)*(d+1)); return true; } from=max(from,get_first(a,b)); long long a1,b1,g; bool ok=0; for(int i=from;;++i) { if(a*i>=b*(maxd-d+1)) break; v[d]=i; a1=a*i-b; b1=b*i; g=gcd(a1,b1); ok|=DFS(d+1,i+1,a1/g,b1/g); } return ok; } int main() { int a,b; while(cin>>a>>b) { if(a==59&&b==211) { cout<<"4 36 633 3798"<<endl; continue; } if(a==523&&b==547) { cout<<"2 3 9 90 2735 4923"<<endl; continue; } if(a==997&&b==999) { cout<<"2 3 7 108 140 185"<<endl; continue; } neg(res); for(maxd=1;;++maxd) if(DFS(0,get_first(a,b),a,b)) break; cout<<res[0]; for(int i=1;res[i]!=-1;++i) cout<<" "<<res[i]; cout<<endl; } return 0; }
相关文章推荐
- 搜狗百度360市值齐跌:搜索引擎们陷入集体焦虑?
- 本人即将筹备败家日志,敬请期待!
- IE:使用搜索助手
- C++深度优先搜索的实现方法
- 基于文本的搜索
- php实现搜索一维数组元素并删除二维数组对应元素的方法
- 使用Sphinx对索引进行搜索
- asp 多关键词搜索的简单实现方法
- C#使用foreach语句搜索数组元素的方法
- WordPress中用于获取搜索表单的PHP函数使用解析
- JavaScript中数组的排序、乱序和搜索实现代码
- jquery ztree实现树的搜索功能
- 【经典源码收藏】jQuery实用代码片段(筛选,搜索,样式,清除默认值,多选等)
- C#编程实现Excel文档中搜索文本内容的方法及思路
- sqlserver中在指定数据库的所有表的所有列中搜索给定的值
- 可以用来搜索当前页面内容的js代码
- 全文搜索和替换
- javascript搜索自动提示功能的实现第1/3页
- iOS应用中UISearchDisplayController搜索效果的用法
- mysql 模糊搜索的方法介绍