zoukankan      html  css  js  c++  java
  • 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("
    ");
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    ACM: Copying Data 线段树-成段更新-解题报告
    POJ 2488 A Knight's Journey
    POJ 3349 Snowflake Snow Snowflakes Hash
    POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数
    POJ 1035 Spell checker 简单字符串匹配
    POJ 3267 The Cow Lexicon 简单DP
    POJ 1459 Power Network 最大流(Edmonds_Karp算法)
    POJ 3687 Labeling Balls 逆向建图,拓扑排序
    HDU 1532 Drainage Ditches 最大流 (Edmonds_Karp)
    POJ 3026 Borg Maze bfs+Kruskal
  • 原文地址:https://www.cnblogs.com/npugen/p/9581941.html
Copyright © 2011-2022 走看看