1. 程式人生 > >UVA12558-Efyptian Fractions(HARD version)(叠代加深搜索)

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

num watch def 深搜 ini with ins number 最大的

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 }

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