UVA12558-Efyptian Fractions(HARD version)(迭代加深搜索)

Problem UVA12558-Efyptian Fractions(HARD version)

Accept:187  Submit:3183

Time Limit: 3000 mSec

 Problem Description

Given a fraction a/b, write it as a sum of different Egyptian fraction. For example, 2/3 = 1/2 + 1/6. Thereisonerestrictionthough: thereare k restrictedintegersthatshouldnotbeusedasadenominator. For example, if we can’t use 2..6, the best solution is:
2/3 = 1/7 + 1/9 + 1/10 + 1/12 + 1/14 + 1/15 + 1/18 + 1/28 The number of terms should be minimized, and then the large denominator should be minimized. If there are several solutions, the second largest denominator should be minimized etc.

 Input

The first line contains the number of test cases T (T ≤ 100). Each test case begins with three integers a, b, k (2 ≤ a < b ≤ 876, 0 ≤ k ≤ 5, gcd(a,b) = 1). The next line contains k different positive integers not greater than 1000.

 Output

For each test case, print the optimal solution, formatted as below. Extremely Important Notes It’s not difficult to see some inputs are harder than others. For example, these inputs are very hard input for every program I have: 596/829=1/2+1/5+1/54+1/4145+1/7461+1/22383 265/743=1/3+1/44+1/2972+1/4458+1/24519 181/797=1/7+1/12+1/2391+1/3188+1/5579 616/863=1/2+1/5+1/80+1/863+1/13808+1/17260 22/811=1/60+1/100+1/2433+1/20275 732/733=1/2+1/3+1/7+1/45+1/7330+1/20524+1/26388 However, I don’t want to give up this problem due to those hard inputs, so I’d like to restrict the input to “easier” inputs only. I know that it’s not a perfect problem, but it’s true that you can still have fun and learn something, isn’t it? Some tips: 1. Watch out for floating-point errors if you use double to store intermediate result. We didn’t use double. 2. Watch out for arithmetic overflows if you use integers to store intermediate result. We carefully checked our programs for that.

 Sample Input

5

2 3 0

19 45 0

2 3 1 2

5 121 0

5 121 1 33

 Sample Ouput

Case 1: 2/3=1/2+1/6

Case 2: 19/45=1/5+1/6+1/18

Case 3: 2/3=1/3+1/4+1/12

Case 4: 5/121=1/33+1/121+1/363

Case 5: 5/121=1/45+1/55+1/1089

题解:IDA*算法,标注的是困难版本,其实和lrj在之前讲的没什么区别。只要是这个算法,主框架就都是一样的。我在之前的博客里提到过是否需要d==maxd的判断,由于这个题估价函数的特点,这句话是需要的。估价函数很好理解,如果在接下来的搜索中,即便分数的大小都是目前最大的数也无法达到目标,必然就要剪枝。

 1 #include <bits/stdc++.h>
 2
 3 using namespace std;
 4 typedef long long LL;
 5
 6 const int maxn = 1000 + 5;
 7 int k, maxd;
 8 bool canuse[maxn];
 9 LL a, b;
10 LL ans[maxn],v[maxn];
11
12 LL gcd(LL a, LL b) {
13     return b == 0 ? a : gcd(b, a%b);
14 }
15
16 LL get_first(LL a, LL b) {
17     return (b - 1) / a + 1;
18 }
19
20 bool better(int d) {
21     for (int i = d; i >= 0; i--) {
22         if (v[i] != ans[i]) {
23             return ans[i] == -1 || v[i] < ans[i];
24         }
25     }
26     return false;
27 }
28
29 bool dfs(int d, LL from, LL a, LL b) {
30     if (d == maxd) {
31         if (b%a) return false;
32         v[d] = b / a;
33         if (v[d]<=1000 && !canuse[v[d]]) return false;
34         if (better(d)) memcpy(ans, v, (d+1) * sizeof(LL));
35         return true;
36     }
37
38     bool ok = false;
39     for (LL i = max(from, get_first(a, b));; i++) {
40         if(i<=1000 && !canuse[i]) continue;
41         if (b*(maxd + 1 - d) <= i * a) break;
42         v[d] = i;
43         LL b2 = b * i,a2 = a * i - b;
44         LL g = gcd(a2, b2);
45         if (dfs(d + 1, i + 1, a2 / g, b2 / g)) ok = true;
46     }
47     return ok;
48 }
49
50 int main()
51 {
52     int iCase = 1;
53     int T;
54     scanf("%d", &T);
55     while (T--) {
56         scanf("%lld%lld%d", &a, &b, &k);
57         memset(canuse, true, sizeof(canuse));
58         int x;
59         while(k--){
60             scanf("%d", &x);
61             canuse[x] = false;
62         }
63         printf("Case %d: ", iCase++);
64         for (maxd = 0;; maxd++) {
65             memset(ans, -1, sizeof(ans));
66             if (dfs(0,get_first(a,b), a, b)) break;
67         }
68         printf("%lld/%lld=1/%lld", a, b, ans[0]);
69         for (int i = 1; i <= maxd; i++) {
70             printf("+1/%lld", ans[i]);
71         }
72         printf("\n");
73     }
74     return 0;
75 }

原文地址:https://www.cnblogs.com/npugen/p/9581941.html

时间: 2024-11-11 09:23:47

UVA12558-Efyptian Fractions(HARD version)(迭代加深搜索)的相关文章

UVA12558 Egyptian Fractions (HARD version) (埃及分数)

UVA12558 Egyptian Fractions (HARD version) 题解 迭代加深搜索,适用于无上界的搜索.每次在一个限定范围中搜索,如果无解再进一步扩大查找范围. 本题中没有分数个数和分母的上限,只用爆搜绝对TLE.故只能用迭代加深搜索. #include<cstdio> #include<cstring> #include<set> using namespace std; typedef long long ll; int num,T,t,k;

UVA-11214 Guarding the Chessboard (迭代加深搜索)

题目大意:在一个国际象棋盘上放置皇后,使得目标全部被占领,求最少的皇后个数. 题目分析:迭代加深搜索,否则超时. 小技巧:用vis[0][r].vis[1][c].vis[2][r+c].vis[c-r+N]分别标志(r,c)位置相对应的行.列.主.副对角线有没有被占领(详见<入门经典(第2版)>P193),其中N表示任意一个比行数和列数都大(大于等于)的数. 代码如下: # include<iostream> # include<cstdio> # include&l

USACO/fence8 迭代加深搜索+剪枝

题目链接 迭代加深搜索思想. 枚举答案K,考虑到能否切出K个木头,那么我们当然选最小的K个来切. 1.对于原材料,我们是首选最大的还是最小的?显然,首选大的能够更容易切出,也更容易得到答案. 2.对于目标木头,我们是优先得到最大的还是最小的?显然,由于K个木头我们都要得到,那么当然先把最大的(最难得到的)先得到,这种搜索策略更优. 3.假设总原材料为all,前K个木头总和为sum,那么all-sum就是这一次切割过程中能[浪费]的最大数目.对于一个切剩下的原材料,若它比最小的目标木头还要小,则它

hdu 1560 DNA sequence(迭代加深搜索)

DNA sequence Time Limit : 15000/5000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 15   Accepted Submission(s) : 7 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description The twenty-first century

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

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

hdu 1560 迭代加深搜索

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1560 只能说bin神太给力了.. 又学到不少新知识.. 迭代加深搜索,貌似 又叫IDA*, 就是给搜索深度一个限制,搜索到一个满足条件就结束. 注意剪枝~ 代码: #include <iostream> #include <cstdio> #include <cstring> using namespace std; char g[10][10]; int size[10];

【wikioi】2495 水叮当的舞步(A*+迭代加深搜索)

这题我还是看题解啊囧.(搜索实在太弱.完全没想到A*,还有看题的时候想错了,.,- -) 好吧,估价还是那么的简单,判断颜色不同的数目即可(左上角的联通块不算在内) 然后A*还是一样的做法. 迭代加深还是一样的味道- 在这里我们用c[i][j]来表示左上角开始的联通块和联通块外面一层(因为要从外面一层拓展颜色),分别记为1和2 那么我们在搜索的时候,染色只要染c[i][j]为2的颜色种类,并且更新联通块(在这里不需要传图,因为一层一层的拓展下去的话,是单调递增的,所以用不到之前的颜色)我们在搜索

hdu 2485 Destroying the bus stations 迭代加深搜索

求最少去掉几个公交站使得从s到t的最短路径大于k. 迭代加深搜索. #include <cstdio> #include <cstring> #include <queue> using namespace std; #define maxn 60 #define maxm 50000 int n,m,K,cnt,up; int head[maxn],pre[maxn]; int road[maxn][maxn]; bool del[maxn]; queue<in

UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: 3)采用广度优先搜索结点数越来越多,耗时过大: 经过简单计算,最长大概10次左右的变换就能出解,于是笔者就尝试采用IDA*,迭代加深搜索的好处是: 1)无需存储状态,节约时间和空间: 2)深度优先搜索查找的结点数少: 3)递归方便剪枝: 代码如下: 1 #include <iostream> 2