• 计蒜课_无脑博士的试管们


    问题描述:

    无脑博士有三个容量分别是 A,B,CA,B,C 升的试管,A,B,CA,B,C 分别是三个从 11 到 2020 的整数,最初,AA 和 BB 试管都是空的,而 CC 试管是装满硫酸铜溶液的。有时,无脑博士把硫酸铜溶液从一个试管倒到另一个试管中,直到被灌试管装满或原试管空了。当然每一次灌注都是完全的。由于无脑博士天天这么折腾,早已熟练,溶液在倒的过程中不会有丢失。

    写一个程序去帮助无脑博士找出当 AA 试管是空的时候,CC 试管中硫酸铜溶液所剩量的所有可能性。

    输入格式

    输入包括一行,为空格分隔开的三个数,分别为整数 A,B,CA,B,C。

    输出格式

    输出包括一行,升序地列出当 AA 试管是空的时候,CC 试管溶液所剩量的所有可能性。

    样例输入

    2 5 10
    样例输出

    5 6 7 8 9 10

    解题思路:

    思路比较简单,使用一个三元组(ca,cb,cc),三个变量分别代表某个操作后,A,B,C三个试管中溶液的体积;对于当前的A,B,C,可以有六种操作,A->B,A->C;B->A,B->C;C->A,C->B;并由此最多可以产生六种状态。然后对六种状态分别进行同样的操作,类似于深度优先搜索。并在状态转变过程中,记录(ca,cb,cc)中满足要求的cc.最后进行输出。具体代码如下。

    #include<iostream>
    #include<set>
    using namespace std;
    bool x2y(int cx,int cy,int x,int y,int*p) {//主要用于判断x->y的操作是否可行,以及操作后的数据;
        if (cx == 0 || y ==cy)
            return false;
        if (y - cy >= cx) {
            cy += cx;
            cx = 0;
        }else {
            cx -= (y - cy);
            cy = y;
        }
        p[0] = cx;
        p[1] = cy;
        return true;
    }
    
    void DFS(bool(*test)[21][21],set<int>&res,int ca,int cb,int cc,int a,int b,int c){
        if (test[ca][cb][cc] == true)//如果此状态已经检测过,那么直接返回;
            return;
        if (ca == 0) {//对符合条件的cc进行插入;
            res.insert(cc);
        }
        test[ca][cb][cc] = true;//修改该元组的状态;
        int p[2];
        if (x2y(ca,cb,a,b,p)) {//以下的判断为对可能的六种状态检测;
            DFS(test,res,p[0],p[1],cc,a,b,c);
        }
        if (x2y(ca,cc,a,c,p)) {
            DFS(test, res, p[0], cb, p[1], a, b, c);
        }
        if (x2y(cb, ca, b, a,p)) {
            DFS(test, res, p[1], p[0], cc, a, b, c);
        }
        if (x2y(cb, cc, b, c,p)) {
            DFS(test, res, ca, p[0], p[1], a, b, c);
        }
        if (x2y(cc, ca, c, a,p)) {
            DFS(test, res, p[1],cb, p[0], a, b, c);
        }
        if (x2y(cc, cb, c, b,p)) {
            DFS(test, res, ca, p[1],p[0], a, b, c);
        }
    }
    
    void input() {
        int a;
        int b;
        int c;
        cin >> a >> b >> c;
        bool test[21][21][21]={false};//主要用于记录当前的状态是否已经进行过状态转换的检测;
        set<int>res;//主要记录符合条件的cc并进行排序。
        DFS(test,res,0,0,c,a,b,c);
        for (set<int>::iterator it = res.begin();it!=--res.end();++it) {
            cout << *it <<" ";
        }
        cout<<*(--res.end());//主要是对输出格式的控制,使之符合要求。
    }
    int main(){
        input();
        return 0;
    }
    

    时间复杂度分析:最多检测的状态个数为(O(abc));满足条件的cc插入set中的时间为(lg 1 + lg 2+ lg 3 + ... + lg(abc) = O(2 lg (abc)));
    因此总的时间复杂度为(O(abc));

    如有不当,欢迎指正 :)
  • 相关阅读:
    SVN
    jenkins可视化
    Tomcat
    防火墙
    keepalived
    MHA高可用
    http
    inotifywait
    DNS
    nginx
  • 原文地址:https://www.cnblogs.com/lif323/p/7411762.html
Copyright © 2020-2023  润新知