Vijos 1308 埃及分数 - 迭代加深

时间:2023-03-09 22:32:49
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

(来自https://vijos.org/p/1308


这道题很明显使用搜索

(1)深搜,不知道深度

(2)广搜,保存的数据量可能会过大

(3)迭代加深,剪剪枝时间应该可以过

那就用迭代加深

不过还有一些问题:

(1)从哪开始枚举分母

  前面剩下分数的倒数取整和前一个分母+1的最小值

  第二个很好理解,至于第一个:

  假设前面剩下了a/b,则用[b/a]作分母,新分数可能会比原分数大一点点

 所以可以做开始的条件

(2)结束为(最大深度-当前深度+1)*(b/a)取整

Code

 /**
*Vijos.org &codevs.cn
*Problem#1308 Problem#1288
*Accepted Accepted
*Time:528ms 741ms
*Memort:564k 256k
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
#define ll long long
#define _max(a,b) (a>b)?(a):(b)
using namespace std;
/**
*定义分数类
*/
typedef bool boolean;
typedef class MyClass{
public:
int s;
int m;
MyClass():s(),m(){}
MyClass(int s,int m):s(s),m(m){}
#undef int
MyClass operator -(MyClass another){
MyClass result;
int g=getCommon(this->m,another.s);
result.m=this->m*another.m/g;
result.s=this->s*another.m/g-this->m/g*another.s;
int g1=getCommon(result.m,result.s);
result.m/=g1;
result.s/=g1;
return result;
}
boolean empty(){
return (m==);
}
boolean operator <(MyClass another){
if(another.empty()) return true;
if(this->empty()) return false;
if(this->s==another.s) return this->m>another.m;
return (this->s*1.0/this->m)<(another.s*1.0/another.m);
}
boolean operator <(double another){
if(this->empty()) return false;
return (this->s*1.0/this->m)<another;
}
inline int getrInt(){
// if(s==0) return -1;
return (int)(this->m/this->s);
}
boolean isWorkable(){
if(this->empty()) return false;
return (m%s==);
}
void operator <<(istream &in){
in>>s>>m;
}
private:
int getCommon(ll a,ll b){
if(b==) return a;
return getCommon(b,a%b);
}
}MyClass;
MyClass maxx;
int results[];
int list[];
int found = ; /**
*迭代加深
*/
void search(int depthLimit,int now,MyClass fs){
if(fs<) return ;
if(now>depthLimit) return ;
if(fs.isWorkable()&&(fs.m>list[now-])&&(found==||maxx<fs)){
maxx=fs;
results[depthLimit]=fs.m/fs.s;
memcpy(results,list,sizeof(int)*depthLimit);
found=depthLimit;
return ;
}
for(int i=_max(fs.getrInt(),list[now-]+);i<=(depthLimit-now+)*fs.getrInt();i++){
list[now]=i;
search(depthLimit,now+,fs-MyClass(,i));
}
}
int main(){
MyClass q;
q<<cin;
// cout<<q.getrInt();
int i=;
list[]=;
while(found==){
search(i,,q);
i++;
}
for(int i=;i<=found;i++){
printf("%d ",results[i]);
}
}

迭代加深