CODE[VS] 1288 埃及分数
2016-09-04 11:46
295 查看
题目描述 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/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),编程计算最好的表达方式。
输入描述 Input Description
a b
输出描述 Output Description
若干个数,自小到大排列,依次是单位分数的分母。
样例输入 Sample Input
19 45
样例输出 Sample Output
5 6 18
数据范围及提示 Data Size & Hint
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
第一次用memcpy,调试到吐血……然后测出来用法是 memcpy(被赋值数组,被复制数组,长度),可以+1。
然后,也是第一次用迭代加深搜索,因为没有回溯检查了两个小时……
分子分母的转化还是很巧妙的,具体看代码~
还有每次搜索可以限制分母i的值,大于已算值,因为限制总分数个数所以也要小于现在的分母除以分子再除以个数~
在古埃及,人们使用单位分数的和(形如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),编程计算最好的表达方式。
输入描述 Input Description
a b
输出描述 Output Description
若干个数,自小到大排列,依次是单位分数的分母。
样例输入 Sample Input
19 45
样例输出 Sample Output
5 6 18
数据范围及提示 Data Size & Hint
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
第一次用memcpy,调试到吐血……然后测出来用法是 memcpy(被赋值数组,被复制数组,长度),可以+1。
然后,也是第一次用迭代加深搜索,因为没有回溯检查了两个小时……
分子分母的转化还是很巧妙的,具体看代码~
还有每次搜索可以限制分母i的值,大于已算值,因为限制总分数个数所以也要小于现在的分母除以分子再除以个数~
#include<cstdio> #include<cstring> int a,b,tot[1001],ans[1001]; int gcd(int u,int v) { return v ? gcd(v,u%v):u; } void dfs(int u,int v,int aa,int bb) { if(u==v) return; if(bb%aa==0 && bb/aa>tot[tot[0]] && (ans[0]<=0 || ans[ans[0]]>(bb/aa))) //找到后返回(条件:没有原数或比原数末位小) { memcpy(ans,tot,sizeof(tot)); ans[++ans[0]]=bb/aa; return; } int i=bb/aa-1,j=(u-v)*(bb/aa); if(i<=tot[tot[0]]) i=tot[tot[0]]; while(++i<=j) //极限为j { if(ans[0]>0 && ans[ans[0]]<=i) return; int k=gcd(i,bb),z=i/k,x=bb*z,y=aa*z-bb/k; if(y<0) continue; tot[++tot[0]]=i; if(!y) { memcpy(ans,tot,sizeof(tot)); tot[0]--;return; } dfs(u,v+1,y,x); tot[0]--; //回溯! } } int main() { scanf("%d%d",&a,&b); for(int i=1;i<=100;i++) { dfs(i,0,a,b); if(ans[0]) break; } for(int i=1;i<=ans[0];i++) printf("%d ",ans[i]); return 0; }
相关文章推荐
- codevs 1288 埃及分数
- 搜索+剪枝——CODEVS1288 埃及分数
- Codevs P1288 埃及分数
- [codevs1288]埃及分数 迭代加深搜索
- [CODEVS1288]埃及分数(迭代加深搜索)
- codevs1288埃及分数-迭代加深搜索
- codevs1288 埃及分数
- 【基础练习】【IDA*】codevs1288 埃及分数题解
- 【Codevs1288】埃及分数
- [迭代加深搜索] Codevs1288 埃及分数问题
- codevs 1288 埃及分数 迭代加深搜索
- [codevs1288]埃及分数(迭代加深搜索)
- 埃及分数(codevs 1288)
- Codevs 1288 埃及分数 【IDA*】
- Codevs 1288 埃及分数
- [CODEVS1225]埃及分数解题报告
- CODEVS 1288 埃及分数
- 【codevs 1288】【vijos P1308】埃及分数(迭代加深搜)
- 【CodeVS 1288】埃及分数
- [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]