Vijos 1308 埃及分数 - 迭代加深
描述
在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数。如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的。对于一个分数a/b,表示方法有很多种,但是哪种最好呢?首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
如:19/45=1/3 + 1/12 + 1/180
19/45=1/3 + 1/15 + 1/45
19/45=1/3 + 1/18 + 1/30,
19/45=1/4 + 1/6 + 1/180
19/45=1/5 + 1/6 + 1/18.
最好的是最后一种,因为1/18比1/180,1/45,1/30,1/180都大。
给出a,b(0<a<b<1000),编程计算最好的表达方式。
输入:a b
输出:若干个数,自小到大排列,依次是单位分数的分母。
样例1
样例输入1
19 45
样例输出1
5 6 18
限制
各个测试点1s
这道题很明显使用搜索
(1)深搜,不知道深度
(2)广搜,保存的数据量可能会过大
(3)迭代加深,剪剪枝时间应该可以过
那就用迭代加深
不过还有一些问题:
(1)从哪开始枚举分母
前面剩下分数的倒数取整和前一个分母+1的最小值
第二个很好理解,至于第一个:
假设前面剩下了a/b,则用[b/a]作分母,新分数可能会比原分数大一点点
所以可以做开始的条件
(2)结束为(最大深度-当前深度+1)*(b/a)取整
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /** 2 *Vijos.org &codevs.cn 3 *Problem#1308 Problem#1288 4 *Accepted Accepted 5 *Time:528ms 741ms 6 *Memort:564k 256k 7 */ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #define int long long 12 #define ll long long 13 #define _max(a,b) (a>b)?(a):(b) 14 using namespace std; 15 /** 16 *定义分数类 17 */ 18 typedef bool boolean; 19 typedef class MyClass{ 20 public: 21 int s; 22 int m; 23 MyClass():s(0),m(0){} 24 MyClass(int s,int m):s(s),m(m){} 25 #undef int 26 MyClass operator -(MyClass another){ 27 MyClass result; 28 int g=getCommon(this->m,another.s); 29 result.m=this->m*another.m/g; 30 result.s=this->s*another.m/g-this->m/g*another.s; 31 int g1=getCommon(result.m,result.s); 32 result.m/=g1; 33 result.s/=g1; 34 return result; 35 } 36 boolean empty(){ 37 return (m==0); 38 } 39 boolean operator <(MyClass another){ 40 if(another.empty()) return true; 41 if(this->empty()) return false; 42 if(this->s==another.s) return this->m>another.m; 43 return (this->s*1.0/this->m)<(another.s*1.0/another.m); 44 } 45 boolean operator <(double another){ 46 if(this->empty()) return false; 47 return (this->s*1.0/this->m)<another; 48 } 49 inline int getrInt(){ 50 // if(s==0) return -1; 51 return (int)(this->m/this->s); 52 } 53 boolean isWorkable(){ 54 if(this->empty()) return false; 55 return (m%s==0); 56 } 57 void operator <<(istream &in){ 58 in>>s>>m; 59 } 60 private: 61 int getCommon(ll a,ll b){ 62 if(b==0) return a; 63 return getCommon(b,a%b); 64 } 65 }MyClass; 66 MyClass maxx; 67 int results[105]; 68 int list[105]; 69 int found = 0; 70 71 /** 72 *迭代加深 73 */ 74 void search(int depthLimit,int now,MyClass fs){ 75 if(fs<0) return ; 76 if(now>depthLimit) return ; 77 if(fs.isWorkable()&&(fs.m>list[now-1])&&(found==0||maxx<fs)){ 78 maxx=fs; 79 results[depthLimit]=fs.m/fs.s; 80 memcpy(results,list,sizeof(int)*depthLimit); 81 found=depthLimit; 82 return ; 83 } 84 for(int i=_max(fs.getrInt(),list[now-1]+1);i<=(depthLimit-now+1)*fs.getrInt();i++){ 85 list[now]=i; 86 search(depthLimit,now+1,fs-MyClass(1,i)); 87 } 88 } 89 int main(){ 90 MyClass q; 91 q<<cin; 92 // cout<<q.getrInt(); 93 int i=1; 94 list[0]=1; 95 while(found==0){ 96 search(i,1,q); 97 i++; 98 } 99 for(int i=1;i<=found;i++){ 100 printf("%d ",results[i]); 101 } 102 }