E03

  • Problem

    水罐问题,给你两个指定体积的水罐,要求得到目标体积的水量。

  • Code
#include <iostream>
#include <vector>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <sstream>
using namespace std;
class Node {
public:
    Node(int i = 0, int j = 0) {
        set(i, j);
        s = toString();
        fn = -1;
        step = 0;
    }
    void set(int i, int j) {
        first = i;
        second = j;
    }
    void after(Node &from) {
        s = from.s + "->" + toString();
        step = from.step + 1;
    }
    void freshFn(int &final) {
        fn = step + min(abs(final - first), abs(final - second));
    }
    int first;
    int second;
    string s;
    int fn;
    int step;

    string toString() {
        std::stringstream out1;
        out1 << "(" << first << "," << second << ")";
        return out1.str();
    }
};

string Asearch(Node ini, Node cap, int final, int &counter) {
    vector<Node> q;
    Node cur, temp;
    string str = "not found";
    unordered_map<string, int> finded;
    auto add = [&](Node &t) {
        string s = t.toString();
        if (finded[s] && finded[s] <= t.step) {
            return;
        }
        t.after(cur);
        temp.freshFn(final);
        q.push_back(t);
    };

    q.push_back(ini);

    while (q.size()) {
        cur = q[0];
        q.erase(q.begin());
        finded[cur.toString()] = cur.step;
        counter++;

        if (cur.first == final) {
            str = cur.s;
            break;
        }

        temp = cur;

        // fill first jug;
        if (cur.first < cap.first) {
            temp.set(cap.first, cur.second);
            add(temp);
        }

        if (cur.second < cap.second) {
            temp.set(cur.first, cap.second);
            add(temp);
        }

        //Empty 1st Jug
        if (cur.first > 0) {
            temp.set(0, cur.second);
            add(temp);
        }
        //Empty 2nd Jug
        if (cur.second > 0) {
            temp.set(cur.first, 0);
            add(temp);
        }
        // Pour from 1st jug to 2nd jug
        if (cur.first && cur.second < cap.second) {
            int dis = min(cur.first, cap.second - cur.second);
            temp.set(cur.first - dis, cur.second + dis);
            if (dis) {
                add(temp);
            }

        }
        // Pour from 2nd jug to 1st jug
        if (cur.second && cur.first < cap.first) {
            int dis = min(cur.second, cap.first - cur.first);
            temp.set(cur.first + dis, cur.second - dis);
            if (dis) {
                add(temp);
            }
        }

        sort(q.begin(), q.end(), [&](const Node& a, const Node& b) {
            return a.fn < b.fn;
        });

    }

    return str;
}


int main()
{

    //Using BSF to find the answer
    while (true) {
        Node cap, ini;
        int final;

        //Input initial values
        cout << "Enter the capacity of 2 jugs\n";
        cin >> cap.first >> cap.second;
        //input final values
        cout << "Enter the required jug config\n";
        cin >> final;

        int counter = 0;
        cout << "result: " << Asearch(ini, cap, final, counter) << endl;
        cout << "check times: " << counter << endl << endl;
    }

    return 0;
}
  • Result

    E03