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

问题描述:

无脑博士有三个容量分别是 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));

如有不当,欢迎指正 :)
原文地址:https://www.cnblogs.com/lif323/p/7411762.html