leetcode 365. Water and Jug Problem DFS BFS

题目链接

额,先声明一下这两种方法都会超时,但是从解题思路上来说DFS和BFS确实是一种方向。所以实现了一下。(毕竟想不到用GCD做)。想AC的请看这里

DFS
  1. 用dfs做其实就是要确定状态,转移到下一状态以及回溯到上一状态
    我选的状态是(jug0, jug1, jug2),分别代表三个罐子内的水量。为什么是三个罐子?题目中“an infinite amount of water”可以看做是一个有无限水、容量也是无限的罐子。这样问题就成了三个罐子之间的倒水问题,个人感觉问题简化了一些。
  2. 转移到下一状态。共有六种情况,需要根据两只罐子的情况进行转移。
  3. 回溯。在转移到下一状态时需要就行判断,这就让回溯的时候很难知道回溯到什么状态。用双向队列可以很好地解决这个问题:转移到下一状态时,把下一状态加入到队列中;回溯的时候再将它移除就可以。
// C#  Time Limit Exceeded
public class Solution
{
    struct State
    {
        public State(long x, long y, long z)
        {
            jug = new long[3] {x, y, z };
        }

        public long[] jug;
        //对倒水的合法性进行判断:倒出的罐子必须有水,倒入的罐子不能是满的
        public bool IsValid(int from, int to)
        {
            return jug[from] != 0 && jug[to] != capicity[to];
        }
        public void Dump(int from, int to)
        {
            long dumpWater = capicity[to] - jug[to];
            if (jug[from] >= dumpWater)
            {
                jug[from] -= dumpWater;
                jug[to] += dumpWater;
            }
            else
            {
                jug[to] += jug[from];
                jug[from] = 0;
            }
        }
    }
    //记录状态,防止重复访问节点
    List<State> states = new List<State>();
    static public long[] capicity = new long[3];
    public long target = 0;

    public bool CanMeasureWater(int x, int y, int z)
    {
        capicity[0] = x;
        capicity[1] = y;
        capicity[2] = long.MaxValue;//用long.MaxValue来假装是一个无穷大的罐子
        target = z;
        State s = new State(0, 0, int.MaxValue);//用int.MaxValue假装是个有无限多水的罐子
        states.Add(s);
        return Work();
    }

    private bool Work()
    {
        State s = states[states.Count - 1];
        if (s.jug[0] + s.jug[1] == target)
        {
            return true;
        }
        for (int from = 0;from < 3;++from)
            for (int to = 0; to < 3; ++to)
            {
                if (from != to)
                {
                    State next = new State(s.jug[0], s.jug[1], s.jug[2]);
                    if (next.IsValid(from, to))
                    {
                        next.Dump(from, to);
                        //查看当前队列中是否有next
                        bool isContain = states.Exists(x => x.jug[0] == next.jug[0] && x.jug[1] == next.jug[1] && x.jug[2] == next.jug[2]);
                        if (isContain == false)
                        {
                            states.Add(next);
                            if (Work()) return true;//转移到下一状态
                            states.RemoveAt(states.Count - 1);//回溯
                        }
                    }
                }
            }
        return false;
    }
}
BFS

逛讨论区发现有人用BFS写,不过也是超时了。原贴链接:Breadth-First-Search-with-explanation

//python Time Limit Exceeded
class Solution(object):
    def canMeasureWater(self, x, y, z):
        """
        :type x: int
        :type y: int
        :type z: int
        :rtype: bool
        """
        if x > y:
            temp = x;
            x = y;
            y = temp;

        if z > x + y:
            return False;

        # set the initial state will empty jars;
        queue = [(0, 0)];
        visited = set((0, 0));
        while len(queue) > 0:
            a, b = queue.pop(0);
            if a + b == z:
                return True;

            states = set()

            states.add((x, b)) # fill jar x;
            states.add((a, y)) # fill jar y;
            states.add((0, b)) # empty jar x;
            states.add((a, 0)) # empty jar y;
            states.add((min(x, b + a), 0 if b < x - a else b - (x - a))) # pour jar y to x;
            states.add((0 if a + b < y else a - (y - b), min(b + a, y))) # pour jar x to y;

            for state in states:
                if state in visited:
                    continue;
                queue.append(state)
                visited.add(state);

        return False;

猜你喜欢

转载自blog.csdn.net/guojunxiu/article/details/81978474