程序设计Week2作业题B_倒水问题

题意:
给你两个容器,容量分别为A, B ,问是否能够经过有限的步骤倒水, 得到容量为 C 的水。
输入:
输入包含多组数据。每组数据输入 A, B, C 数据范围 0 < A <= B 、C <= B <=1000 、A和B互质。
输出:
你的程序的输出将由一系列的指令组成。这些输出行将导致某一个罐子(不指定是哪一个罐子)正好包含C单位的水。每组数据的最后一行输出应该是“success”。输出行从第1列开始,不应该有空行或任何尾随空格。“fill A” 表示倒满A杯,"empty A"表示倒空A杯,“pour A B” 表示把A的水倒到B杯并且把B杯倒满或A倒空,以此类推。
输入样例:
2 7 5
2 7 4
输出样例:
fill B
pour B A
success
fill A
pour A B
fill A
pour A B
success
解题思路:
如果是上BFS算法程序设计课之前,我大概只隐约记得离散数学上讲过好像要用到状态转移方程的思想,似乎还与图论有关。现在知道了这是一类叫做隐式图问题的图论问题,属于BFS遍历算法的应用。题目中的每一种水的状态都对对应于图中的一个点,题意就是从其实状态所代表的点寻找路径到最终状态所表示的点,且每一个点不要重复访问(即不重复到达之前的状态)。助教在课上也给出了自己的参考代码,用结构体来书写每个水杯的状态status,建立的BFS使用的队列也是status结构体类型的,映射map<Status, bool> mp用来表示某一状态是否被访问过,类似于vis二维数组,映射map<Status, string> from用来记录每个状态由来所经过的动作,例如:“pour A B”,便于后面输出这些动作(即状态转移的过程)。映射map<Status,Status> from2用来记录每一个状态的前继状态。遍历过程和一般的BFS遍历类似,只是每一个点成为了每一种状态。最后输出依然可以选择递归实现或利用vector(stack)。
注意事项:
1、map会对status结构体进行自动排序,故必须重载运算符’<’。
2、由于题目要求处理多种不同的情况,因此每次进入循环前要清空所要用到的数据结构。
参考代码:

#include <bits/stdc++.h>
using namespace std;

int A, B, C;

struct Status {
    int x, y;

    Status() {}

    Status(int _x, int _y) {
        x = _x;
        y = _y;
    }

    bool operator<(const Status &b) const {
        return x == b.x ? y < b.y : x < b.x;
    }



    Status AToB() {
        Status c;
        c.x = max(x + y - B, 0);
        c.y = min(B, x + y);
        return c;
    }

    Status BToA() {
        Status c;
        c.y = max(x + y - A, 0);
        c.x = min(A, x + y);
        return c;
    }

    Status FillA() {
        return Status(A, y);
    }

    Status FillB() {
        return Status(x, B);
    }

    Status EmptyA() {
        return Status(0, y);
    }

    Status EmptyB() {
        return Status(x, 0);
    }
};

map<Status, bool> mp;
map<Status, string> from;
map<Status,Status> from2;
queue<Status> q;
void print(Status t) {
    if (from.find(t) != from.end()) {
        print(from2[t]);
        cout<<from[t]<<endl;
    }
}


void bfs(int a, int b) {
    Status t(a, b);
    q.push(t);
    mp[t] = 1;
    while (!q.empty()) {
        t = q.front();
        q.pop();
        if (t.x == C || t.y == C) {
            print(t);
            return;
        }
        
        Status x=t.AToB();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="pour A B";
            from2[x]=t;
           }
         x=t.BToA();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="pour B A";
            from2[x]=t;
           }
         x=t.FillA();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="fill A";
            from2[x]=t;
           }
        x=t.FillB();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="fill B";
            from2[x]=t;
           }
         x=t.EmptyA();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="empty A";
            from2[x]=t;
           }
        x=t.EmptyB();
        if (mp[x] == 0) {
               mp[x] = 1;
               q.push(x);
            from[x]="empty B";
            from2[x]=t;
           }
        

    }
}

int main() {
    while (cin >> A >> B >> C) {
        mp.clear();
        from.clear();
        from2.clear();
        ans.clear();
        while (!q.empty())q.pop();
        bfs(0, 0);
        cout<<"success"<<endl;
    }
    return 0;
}
发布了5 篇原创文章 · 获赞 5 · 访问量 160

猜你喜欢

转载自blog.csdn.net/weixin_43637016/article/details/104565578
今日推荐