365. 水壶问题

有两个容量分别为 x升 和 y升 的水壶以及无限多的水。请判断能否通过使用这两个水壶,从而可以得到恰好 z升 的水?

如果可以,最后请用以上水壶中的一或两个来盛放取得的 z升 水。

你允许:

装满任意一个水壶
清空任意一个水壶
从一个水壶向另外一个水壶倒水,直到装满或者倒空

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/water-and-jug-problem
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

搜索

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Set;

class Solution {

    private String getKey(int x, int y) {
        return x + "_" + y;
    }

    private void add(LinkedList<State> queue, Set<String> stateSet, int x, int y) {
        String key = getKey(x, y);
        if (!stateSet.contains(key)) {
            queue.offer(new State(x, y));
            stateSet.add(key);
        }
    }

    public boolean canMeasureWater(int x, int y, int z) {
        LinkedList<State> queue = new LinkedList<>();
        Set<String> stateSet = new HashSet<>();
        add(queue, stateSet, 0, 0);
        while (!queue.isEmpty()) {
            State state = queue.poll();
            if (state.x == z || state.y == z || state.x + state.y == z) {
                return true;
            }
            add(queue, stateSet, 0, state.y);
            add(queue, stateSet, state.x, 0);
            add(queue, stateSet, x, state.y);
            add(queue, stateSet, state.x, y);
            add(queue, stateSet, state.x + Math.min(state.y, x - state.x), state.y - Math.min(state.y, x - state.x));
            add(queue, stateSet, state.x - Math.min(state.x, y - state.y), state.y + Math.min(state.x, y - state.y));
        }
        return false;
    }
}

class State {
    int x;
    int y;

    public State(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        State state = (State) o;
        return x == state.x &&
                y == state.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

贝祖定理

class Solution {

    private int gcd(int x, int y) {
        while (y != 0) {
            int remainder = x % y;
            x = y;
            y = remainder;
        }
        return x;
    }

    public boolean canMeasureWater(int x, int y, int z) {
        if (x + y < z) {
            return false;
        }

        if (x == z || y == z || x + y == z) {
            return true;
        }
        return z % gcd(x, y) == 0;
    }
}
posted @ 2021-12-09 11:27  Tianyiya  阅读(29)  评论(0)    收藏  举报