[题解]埃及分数(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:

  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 }

迭代加深

时间: 2024-11-10 14:26:43

[题解]埃及分数(vijos 1308)的相关文章

Vijos 1308 埃及分数(迭代加深搜索)

题意: 输入a.b, 求a/b 可以由多少个埃及分数组成. 埃及分数是形如1/a , a是自然数的分数. 如2/3 = 1/2 + 1/6, 但埃及分数中不允许有相同的 ,如不可以2/3 = 1/3 + 1/3. 求出可以表达a/b个数最少埃及分数方案, 如果个数相同则选取最小的分数最大. #include <bits/stdc++.h> #define LL long long using namespace std; int maxd; long long v[1234],ans[1234

一本通例题埃及分数—题解&amp;&amp;深搜的剪枝技巧总结

一.简述: 众所周知,深搜(深度优先搜索)的时间复杂度在不加任何优化的情况下是非常慢的,一般都是指数级别的时间复杂度,在题目严格的时间限制下难以通过.所以大多数搜索算法都需要优化.形象地看,搜索的优化过程就像将搜索树上没用的枝条剪下来,因此搜索的优化过程又叫剪枝.剪枝的实质就是通过判断决定是否要沿当前枝条走下去. 二.搜索的剪枝必需遵循三个原则: 1.正确性(不能把正解排除,要不然搜什么呢?)2.准确性(尽可能把不能通向正解的枝条剪去)3.高效性(因为在每个枝条上都要进行一次判断,如果判断的复杂

1288 埃及分数

1288 埃及分数 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 在古埃及,人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数. 如:2/3=1/2+1/6,但不允许2/3=1/3+1/3,因为加数中有相同的. 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越 好. 如: 19/45=1/3 + 1/12 + 1/

埃及分数&amp;&amp;The Rotation Game&amp;&amp;骑士精神——IDA*

IDA*:非常好用的搜索,可以解决很多深度浅,但是规模大的搜索问题. 估价函数设计思路:观察一步最多能向答案靠近多少. 埃及分数 题目大意: 给出一个分数,由分子a 和分母b 构成,现在要你分解成一系列互不相同的单位分数(形如:1/a,即分子为1),要求:分解成的单位分数数量越少越好,如果数量一样,最小的那个单位分数越大越好. 如: 19/45 = 1/3 + 1/12 + 1/180; 19/45 = 1/5 + 1/6 + 1/18; 以上两种分解方法都要3个单位分数,但下面一个的最小单位分

【迭代加深搜索】埃及分数问题

谢谢阿苏~http://blog.csdn.net/urecvbnkuhbh_54245df/article/details/5856756 [迭代加深搜索(ID,iterative deepening)]:从小到大枚举上限maxd,每次执行只考虑深度不超过maxd的结点. ------对于可以用回溯法求解但解答树的深度没有明显上限的题目,可以考虑ID算法: ------优点:它主要是在递归搜索函数的开头判断当前搜索的深度是否大于预定义的最大搜索深度,如果大于,就退出这一层的搜索,如果不大于,就

将真数分解为埃及分数

问题: 输入一个分数,将该分数分解为埃及分数. 真分数:分子小于分母的分数 埃及分数:分子为一的分数 #include <stdio.h> #include <stdlib.h> /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char *argv[]) { long in

埃及分数问题_迭代加深搜索_C++

一.题目背景 http://codevs.cn/problem/1288/ 给出一个真分数,求用最少的1/a形式的分数表示出这个真分数,在数量相同的情况下保证最小的分数最大,且每个分数不同. 如 19/45=1/3 + 1/12 + 1/180 二.迭代加深搜索 迭代加深搜索可以看做带深度限制的DFS. 首先设置一个搜索深度,然后进行DFS,当目前深度达到限制深度后验证当前方案的合理性,更新答案. 不断调整搜索深度,直到找到最优解. 三.埃及分数具体实现 我们用dep限制搜索层数,先从2开始,每

埃及分数,迭代加深

埃及分数题意非常明白,这里就不解释了…… 但是关于最优解的问题,题目并没有说明 原题: 对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好. 然而这并没有考虑一种很恶心的情况:加数一样多,而且最后一个分数一样的时候,哪种情况最优呢? 我先写了个从末尾到开头一位一位判断大小,保证最大的程序,大概只有一半的分数(codevs) 又写了个输出 最先找到的 末尾最大的 方案 的程序,结果90(还是codevs) 我选择放弃,,,

将真分数分解为埃及分数

描述 分子为1的分数称为埃及分数.现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数.如:8/11 = 1/2+1/5+1/55+1/110. 接口说明 /* 功能: 将分数分解为埃及分数序列 输入参数:     String pcRealFraction:真分数(格式“8/11”) 返回值:     String pcEgpytFraction:分解后的埃及分数序列(格式“1/2+1/5+1/55+1/100”) */ public static String  Co