bfs_part wine

Pull carriage

/**
There are 4 wine bottles, their capacities are: 9 liters, 7 liters, 4 liters, and 2 liters. The
starting state is [9,0,0,0], that is to say: the first bottle is full , The others are empty.

It is permissible to pour wine from one bottle into another, but only one bottle can be filled or empty, and there can be no intermediate state.
Such a pouring action is called one operation.

Assuming the bottle's capacity and initial state remain unchanged, for a given target state, how many operations are required to achieve at least?
This question requires you to program to calculate the minimum number of operations.

Input: Final state (separated by spaces)
Output: Minimum number of operations (if it cannot be achieved, output -1)

For example:
input:
9 0 0 0
should output:
0

Input:
6 0 0 3
should output:
-1

Input:
7 2 0 0
should output:
2
*/

//In more cases, the node is not very obvious, it is mostly a "state"
//The bottle is upside down...the state must be limited


import java.util.*;
public class 图的bfs_分酒 {
    
    
  static Set<Node> set = new HashSet<>();
  static int[] v = {
    
    9, 7, 4, 2};
  static Queue<Node> queue = new LinkedList<>();
  static Node beginNode = new Node("9,0,0,0", 0);
  static Node finalNode;

  public static void main(String[] args) {
    
    
    Scanner scanner = new Scanner(System.in);
    //接受四个整数
    String finalState = "";
    finalState += scanner.nextInt() + ",";
    finalState += scanner.nextInt() + ",";
    finalState += scanner.nextInt() + ",";
    finalState += scanner.nextInt();
    finalNode = new Node(finalState);
    add(queue, beginNode);
    int res = bfs();
    System.out.println(res);
  }

  private static void add(Queue<Node> queue, Node node) {
    
    
    if (!set.contains(node)) {
    
    
      set.add(node);
      queue.add(node);
    }
  }

  private static int bfs() {
    
    
    while (!queue.isEmpty()) {
    
    
      Node now = queue.poll();//弹出一个
      //如果和目标吻合,则返回
      if (now.equals(finalNode)) {
    
    
        return now.depth;
      }
      //把neighbors(一步操作得到的下一种状态)加入队列
      //先把每个瓶子里面的量得到
      int[] state = now.getState();
      //i是往外倒的
      for (int i = 0; i < state.length; i++) {
    
    
        if (state[i] > 0) {
    
    //有酒,如2 7 0 0
          //j是接收的
          for (int j = 0; j < state.length; j++) {
    
    
            if (j == i) continue;
            //把i倒完的条件
            int j_KongJian = v[j] - state[j];
            if (j_KongJian >= state[i]) {
    
    
              //形成新状态
              int temp = state[i];
              state[i] = 0;
              state[j] += temp;
              add(queue, new Node(intArr2String(state), now.depth + 1));
              //恢复
              state[i] = temp;
              state[j] -= state[i];
            }

            //把j倒满,j有空间,且i能倒完
            if (j_KongJian > 0 && state[i] >= j_KongJian) {
    
    
              int temp = state[i];
              state[i] -= j_KongJian;
              state[j] += j_KongJian;
              add(queue, new Node(intArr2String(state), now.depth + 1));
              //  恢复
              state[i] = temp;
              state[j] -= j_KongJian;
            }
          }
        }
      }
    }
    return -1;
  }

  private static String intArr2String(int[] state) {
    
    
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < state.length; i++) {
    
    
      sb.append(state[i]).append(",");
    }
    return sb.deleteCharAt(sb.length() - 1).toString();
  }

  static class Node {
    
    
    String val;//9,0,0,0
    int depth;//深度,或者说到达这个状态需要的操作次数

    public Node(String val) {
    
    
      this.val = val;
    }

    public Node(String val, int depth) {
    
    
      this.val = val;
      this.depth = depth;
    }

    //把状态字符串转成四个杯子的存量,方便运算
    public int[] getState() {
    
    
      String[] arr = val.split(",");
      int[] res = new int[arr.length];
      for (int i = 0; i < arr.length; i++) {
    
    
        res[i] = Integer.parseInt(arr[i]);
      }
      return res;
    }

    @Override
    public boolean equals(Object o) {
    
    
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;

      Node node = (Node) o;

      return val.equals(node.val);
    }

    @Override
    public int hashCode() {
    
    
      return val.hashCode();
    }
  }
}

Guess you like

Origin blog.csdn.net/weixin_45952706/article/details/109252974