埃及分数,迭代加深
Posted 汪立超
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了埃及分数,迭代加深相关的知识,希望对你有一定的参考价值。
埃及分数题意非常明白,这里就不解释了……
但是关于最优解的问题,题目并没有说明
原题:
对于一个分数a/b,表示方法有很多种,但是哪种最好呢? 首先,加数少的比加数多的好,其次,加数个数相同的,最小的分数越大越好。
然而这并没有考虑一种很恶心的情况:加数一样多,而且最后一个分数一样的时候,哪种情况最优呢?
我先写了个从末尾到开头一位一位判断大小,保证最大的程序,大概只有一半的分数(codevs)
又写了个输出 最先找到的 末尾最大的 方案 的程序,结果90(还是codevs)
我选择放弃,,,
但是这不影响说明这个迭代加深是对的——只是最优方案找不到而已
其实写一下dfs然后不停的加大最大的搜索深度就可以保证找到加数最少的方案——不用担心重复搜索,总共才多大,而且深度+1以后搜索量会成倍增大,先前的重复搜索在最后一次搜索面前忽略不计(可以这么理解,毕竟这数据不大)
搜索深度最大的那一次搜索也要搜到底,这样能保证找到所有解,以便找出其中的最优解
上个90分代码
1 #include <cstdio> 2 int c[10001],ans[10001]; 3 int k,max,min; 4 int gcd(int a,int b) 5 { 6 if(a%b==0) 7 return b; 8 else 9 return gcd(b,a%b); 10 } 11 bool dfs(int a,int b) 12 { 13 if(k==max) 14 { 15 if((a==1)&&(b>=min)) 16 { 17 c[k]=b; 18 if((b<ans[k])||(ans[k]==0)) 19 { 20 for(int j=1;j<=k;j++) 21 ans[j]=c[j]; 22 } 23 return true; 24 } 25 return false; 26 } 27 bool flag=false; 28 int t=min; 29 for(int i=min;i<=(max-k+1)*b/a;i++) 30 { 31 c[k]=i; 32 int B=b*i; 33 int A=a*i-b; 34 if(A<0) 35 continue; 36 int gc=gcd(B,A); 37 A/=gc; 38 B/=gc; 39 k++; 40 min=i+1; 41 if (dfs(A,B)) 42 flag=true; 43 k--; 44 min=t; 45 } 46 return flag; 47 } 48 int main() 49 { 50 int a,b; 51 scanf("%d%d",&a,&b); 52 for(int i=1;1;i++) 53 { 54 k=1;max=i;min=1; 55 if (dfs(a,b)) 56 { 57 for(int j=1;j<=i;j++) 58 printf("%d ",ans[j]); 59 break; 60 } 61 } 62 return 0; 63 }
可以看出代码非常短——只是一开始我为了写分数,开了个struct,但后来发现只是白白增加代码量,于是删光重构
这里需要说明的是每一次搜索的宽度:
我们不妨设先找到的数总是最大的(很容易做到,只要每次从上一次的分母+1开始找下一次的分母就能保证),所以如果一个加入的数乘上以后可能加上的数的总数都还到不了目标(因为后出现的更小),则可以直接剪掉,这就实现了对每一层宽度的限制——也就保证了算法可以结束
反正代码短,其实一行一行理解一下也很方便,建议看一下,还是有一些细节的
以上是关于埃及分数,迭代加深的主要内容,如果未能解决你的问题,请参考以下文章