首页 > 其他 > 详细

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

时间:2019-08-14 09:16:15      阅读:86      评论:0      收藏:0      [点我收藏+]

笔记就 懒得搞得有多好看了 自己看的顺就行

贴个luogu链接 uva比较慢 UVA12558 埃及分数 Egyptian Fractions (HARD version)

一开始看着紫书写的 就是添加了个约束条件 现在理解了之后搞一个

 

题目是搜索  考虑BFS 状态数太多 一次要向不知道数量个状态转移 不行

       考虑DFS 解决了状态数过多的问题 但是深度太深了 也不行

  所以就IDDFS解决 每次把a/b减去一个1/c 直到到达深度限制且最后减去的为埃及分数并且分母不受限

代码

#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;

using std::cin;
using std::cout;
using std::endl;

std::map<ll, int>map;  //利用map来判断能不能用
ll ans[105], tmp[105];  //存答案

ll gcd(ll a, ll b) {if(a < b) std::swap(a, b); return b == 0 ? a : gcd(b, a % b);}  
//不知道static_cast和(int)()有什么区别 不过看着很吊就是了
ll get_first(ll a, ll b) {return static_cast<int>(b / a) + 1;}  //得到1/c <= a/b的c的最大值 由1/c <= a/b可推导出b <= a * c 进而推导出b / a <= c

bool check(int dep) {  //判断最优解
    for(int i = dep; i >= 0; i--) 
        if(ans[i] != tmp[i]) return ans[i] == -1 || ans[i] > tmp[i];  //要求的是分母最小 ans[i] == -1判断
    return false;
}

void replace(int dep) {for(int i = 0; i <= dep; i++) ans[i] = tmp[i];}

bool IDDFS(int dep_lim, int dep, ll up, ll down, ll min) {  //dep_lim为深度限制 dep为当前深度 up为剩下的分子 down为剩下的分母
    bool flag = false;  //因为是最优解 而第一个搜到的不一定是最优解 所以不能够搜到直接return
    if(dep >= dep_lim) {  //深度大于等于限制是就需要判断了
        if(down % up) return false;  //因为埃及分数的分子只能为1(然而那题题面没写)所以如果分子不是1就不是答案
        tmp[dep] = down / up;  //得到分母 存入答案
        if(map.count(tmp[dep])) return false;  //如果分母不能用就不是
        if(check(dep)) replace(dep);  //更新最优解
        return true;
    }
    for(int i = std::max(min, get_first(up, down)); ; i++) {  //因为最后得出的那个的分母是递增的 所以遍历下界的第一个条件为上次的分母,也就是min 另外一个条件为1/c <= a/b时c的最小值,因为如果1/c > a/b,那么就不会有结果
        if(down * (dep_lim - dep + 1) <= up * i) break;  //如果剩下几个全为1/i,加起来也不超过up/down就直接break,因为随着i的增大1/i只会越来越小,由(dep_lim - dep + 1) * (1 / i) < up / down可推导出
        if(map.count(i)) continue;  //如果i为受限的分母 就不能选
        tmp[dep] = i;  //存答案
        ll b = i * down;  //由up/down - 1/i = a/b可得出 up/down - 1/i = a/b --> (up * i)/(down * i) - down/(i * down) = a/b --> a = up * i - down, b = down * i
        ll a = up * i - down;
        ll g = gcd(a, b);  //gcd
        if(IDDFS(dep_lim, dep + 1, a/g, b/g, i + 1)) flag = true;  
    }
    return flag;
}

int main() {
    int t;
    scanf("%d", &t);
    int it = 1;
    while(t--) {
        int a, b, k;
        memset(ans, -1, sizeof(ans));
        memset(tmp, -1, sizeof(tmp));
        map.clear();
        scanf("%d%d%d", &a, &b, &k);
        for(int i = 0; i < k; i++) {
            ll tmp;
            scanf("%lld", &tmp);
            map[tmp] = 1;
        }
        int dep = 0;
        while(1) {
            if(IDDFS(dep, 0, a, b, get_first(a, b))) break;
            dep++;
        }
        printf("Case %d: %d/%d=", it++, a, b);
        for(int i = 0; i < dep; i++) printf("1/%d+", ans[i]);
        printf("1/%d\n", ans[dep]);
    }
    system("pause");//上交oj时记得注释或删除
    return 0;
}

不知道cnblogs怎么用latex就没用 一些细节也都标出来了 反正也是给自己看

#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;

using std::cin;
using std::cout;
using std::endl;

std::map<ll, int>map;
ll ans[105], tmp[105];

ll gcd(ll a, ll b) {if(a < b) std::swap(a, b); return b == 0 ? a : gcd(b, a % b);}

ll get_first(ll a, ll b) {return static_cast<int>(b / a) + 1;}

bool check(int dep) {
    for(int i = dep; i >= 0; i--) 
        if(ans[i] != tmp[i]) return ans[i] == -1 || ans[i] > tmp[i];
    return false;
}

void replace(int dep) {for(int i = 0; i <= dep; i++) ans[i] = tmp[i];}

bool IDDFS(int dep_lim, int dep, ll up, ll down, ll min) {
    bool flag = false;
    if(dep >= dep_lim) {
        if(down % up) return false;
        tmp[dep] = down / up;
        if(map.count(tmp[dep])) return false;
        if(check(dep)) replace(dep);
        return true;
    }
    for(int i = std::max(min, get_first(up, down)); ; i++) {
        if(down * (dep_lim - dep + 1) <= up * i) break;
        if(map.count(i)) continue;
        tmp[dep] = i;
        ll b = i * down;
        ll a = up * i - down;
        ll g = gcd(a, b);
        if(IDDFS(dep_lim, dep + 1, a, b, i + 1)) flag = true;
    }
    return flag;
}

int main() {
    int t;
    scanf("%d", &t);
    int it = 1;
    while(t--) {
        int a, b, k;
        memset(ans, -1, sizeof(ans));
        memset(tmp, -1, sizeof(tmp));
        map.clear();
        scanf("%d%d%d", &a, &b, &k);
        for(int i = 0; i < k; i++) {
            ll tmp;
            scanf("%lld", &tmp);
            map[tmp] = 1;
        }
        int dep = 0;
        while(1) {
            if(IDDFS(dep, 0, a, b, get_first(a, b))) break;
            dep++;
        }
        printf("Case %d: %d/%d=", it++, a, b);
        for(int i = 0; i < dep; i++) printf("1/%d+", ans[i]);
        printf("1/%d\n", ans[dep]);
    }
    //system("pause");//上交oj时记得注释或删除
    retu

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

原文:https://www.cnblogs.com/Cattttttttt/p/11349594.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!