UVA 12558 埃及分数(迭代搜索)
来源:互联网 发布:mac 安装oracle 编辑:程序博客网 时间:2024/06/07 08:11
【题意】
把a/b写成不同分数之和,且分数分子必须为1,要求项数尽量小,在此前提下最小的分数尽量大,然后第
二小的分数尽量大……另外有k(0<=k<=5)个不超过1000的正整数不能用作分母。
输入保证2<=a<b<=876,gcd(a,b)=1。
【分析】
通过之前看的简单的埃及分数,知道了大体的求解步骤。
1. 此题需要用迭代加深搜索,如果只dfs,是一个没有下界的搜索,死递归;如果bfs,内存开销大。
2. 选当前分数时,从最接近的值开始,a/b最接近的值就是1/(b/a),然后是结束,结束最大为剩余步数
step*b/a,因为1/(b/a)平均拆成step份,step个分数相加才等于a/b,因为越往后分母越大,如果当前分母都
比step*b/a大,无论后面是多大的分数加和都小于a/b。
3. 将不能出现的正整数用数组标记下来,遍历时进行判断。因为给你不能出现的正整数范围比较小,所以
用数组标记节约时间,如果数据范围大,可以选择用set容器进行存储,进行判断是否当前正整数能使用。使用
数组标记就要注意一个细节,就是正整数不超过1000,所以判断时,先判断是否超过1000,在判断数组,不然
会数组越界。
4. 因为分母会很大,int是存不下的,需要用long long。简单的埃及分数是使用的int。
5. 拆分后的分数项数,没有具体要求所以,最好定大一些,不过此题不用太大,反正10项可以过。
【代码】
#include<stdio.h>#include<string.h>const int N=10;typedef long long LL;LL dep,flag,pre[N],now[N];bool book[1010];// 函数功能:求最大公约数LL gcd(LL a,LL b){ LL temp; while(a!=0) { temp=a; a=b%a; b=temp; } return b;}// 函数功能:遍历第dep步的所有解void dfs(LL a,LL b,LL k){ if(b%a==0&&b/a>now[k-1]&&(b/a>1000||!book[b/a])) // 找到符合要求的结果 { /* 不要忘记判断最后的结果是否能使用,不然会WA,且要记得b/a的范围在1000以内才能判断,不然会数组越界 */ /* 不能把book放下面判断,没有循环continue不能用,return会出错,可能没有到达dep步b%a==0,但是b/a是不能使用的 */ now[k]=b/a; bool ans=0; for(int i=k;i>=1;i--) { if(now[i]<pre[i]) { ans=1; break; } else if(now[i]>pre[i]) break; } if(!flag||ans) memcpy(pre,now,sizeof(now)); flag=1; return ; } LL s=b/a; if(s<=now[k-1]) s=now[k-1]+1; LL t=(dep-k+1)*b/a; // 迭代搜索执行到第dep步就结束了,限制上界 /* 之所以是这个公式是,s是使等式成立最接近的解,把s平均拆分成dep-k+1份,如果没t还小,剩下的dep-k步无论取多少都会偏小 */ if(flag&&t>pre[dep]) t=pre[dep]-1; for(LL i=s;i<=t;i++) { if(i<=1000&&book[i]) // 判断这个点能否使用,不要忘记范围,不要越界访问 continue; now[k]=i; LL m=gcd(a*i-b,b*i); dfs((a*i-b)/m,(b*i)/m,k+1); } return ;}// 函数作用:简洁。可去掉,放在main函数中void slove(LL a,LL b){ now[0]=1; for(dep=2;dep<=N;dep++) { dfs(a,b,1); if(flag) { printf("1/%lld",pre[1]); for(LL i=2;i<=dep;i++) printf("+1/%lld",pre[i]); printf("\n"); return ; } } return ;}int main(){ int T,cnt=1; scanf("%d",&T); while(T--) { flag=0; memset(book,false,sizeof(book)); LL a,b,k,x; scanf("%lld %lld %lld",&a,&b,&k); while(k--) { scanf("%lld",&x); book[x]=true; } printf("Case %d: %lld/%lld=",cnt++,a,b); slove(a,b); } return 0;}
【收获】
1. 认真思考题目的上界是什么。在题目没有给上界或下界时,需要自己去推出
上界(下界),如果推不出来就尽量开大一些。如果没有上界,递归就是死递归。
2. 注意细节。使用数组时,要注意思考下标是否会越界,此题RE了n次。
3. 思考问题,要认真思考。此题结束条件是一个坑,因为有不能使用的正整
数,所以可能没有走到对应的步数或者走到对应步数的正整数不能使用,如果处理
不好就会WA。认真思考结束条件和特殊数据。
4. long long 的使用。
5. 求最大公约数(好久没做过,忘个差不多了)。
- UVA 12558 埃及分数(迭代搜索)
- 埃及分数(迭代加深搜索)
- 埃及分数(迭代加深搜索)
- 埃及分数(迭代加深搜索)
- 迭代加深搜索(埃及分数)
- 埃及分数(迭代加深搜索)
- EOJ 1154/ UVA 12558 埃及分数问题 迭代加深搜索
- 埃及分数(迭代加深搜索)【转】
- 埃及分数(迭代加深搜索)【转】
- vijos1308 埃及分数(迭代加深搜索)
- 埃及分数问题(迭代加深搜索)
- [CODEVS1288]埃及分数(迭代加深搜索)
- 埃及分数问题 迭代加深搜索(IDDFS)
- [codevs1288]埃及分数(迭代加深搜索)
- 埃及分数 迭代加深搜索 IDS
- 迭代加深搜索 埃及分数
- 埃及分数,迭代加深搜索
- 埃及分数题解[迭代加深搜索]
- Mac 下 修改MySQL数据库 密码
- 第十一周OJ——日期妙算星座
- mybatis @param的解释
- Spark 优化
- 关于input[type=file]表单控件的相关知识点
- UVA 12558 埃及分数(迭代搜索)
- 112家it公司薪水
- Java String类
- CentOS 7 安装Java JDK
- algorithm 题集六 (16.11.12)
- UGUI 打字机效果
- [网络安全]dSploit-Android系统下的网络分析和渗透套件的使用
- poj 2251 Dungeon Master (BFS)
- linux内核sysfs详解-1