bfs_partワイン

キャリッジを引く

/ **
ワインボトルは4つあり、容量は9リットル、7リットル、4リットル、2リットルです。
開始状態は[9,0,0,0]、つまり最初のボトルがいっぱいです。 、他は空です。

あるボトルから別のボトルにワインを注ぐことは許可されていますが、1つのボトルのみを充填または空にすることができ、中間状態はあり得ません。
このような注入動作をワンオペレーションと呼びます。

ボトルの容量と初期状態が変わらないと仮定すると、特定のターゲット状態に対して、少なくともそれを達成するためにいくつの操作が必要ですか?
この質問では、操作の最小数を計算するようにプログラムする必要があります。

入力:最終状態(スペースで区切られます)
出力:最小操作数(達成できない場合は、出力-1)

例:
入力:
9 0 0 0
出力:
0

入力:
6 0 0 3
出力:
-1

入力:
7 2 0 0
出力:
2
* /

//多くの場合、ノードはあまり明確ではなく、ほとんどが「状態」です
//ボトルが逆さまになっています...状態を制限する必要があります


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();
    }
  }
}

おすすめ

転載: blog.csdn.net/weixin_45952706/article/details/109252974