大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
7 4 3 4 1 3 0 0 0
NO3
分析:这道题最终的状态就是三个里面只要有两个体积相等同时另一个为零即可,那么由于可能性很多并且步数繁杂,采用广搜是比较好的方法,虽然代码量大,但是基本思路都是重复的,大致思路就是把六种状态都遍历一遍就好了
import java.util.*; public class Main { static Scanner in = new Scanner(System.in); static final int maxn = 105; //标志数组来标记路径,三个杯子三维数组即可 static int[][][] visited = new int[maxn][maxn][maxn]; static void init() { for (int i = 0; i < maxn; ++i) for (int j = 0; j < maxn; ++j) for (int k = 0; k < maxn; ++k) visited[i][j][k] = 0; } // a b c为三个容器的最大容量 static void bfs(int a, int b, int c) { if (a % 2 == 1) { System.out.println("NO"); return; } Queue<Node> que = new LinkedList<Node>(); // 初始 que.add(new Node(a, 0, 0, 0)); while (!que.isEmpty()) { // 取队头并弹出 Node t = que.poll(); visited[t.a][t.b][t.c] = 1; // 判断是否符合条件 if (t.a == t.b && t.c == 0 || t.a == t.c && t.b == 0 || t.b == t.c && t.a == 0) { System.out.println(t.step); return; } // 倒水过程,注意倒水的前提是杯子里面有水 // b -> a if (t.b != 0) { // 因为没有刻度, 所以每次倒水都有两种情况 // 第一种情况是把自己倒完 if (t.a + t.b <= a) { if (visited[t.a + t.b][0][t.c] == 0) { que.add(new Node(t.a + t.b, 0, t.c, t.step + 1)); visited[t.a + t.b][0][t.c] = 1; } } // 第二种情况是把对方倒满 else if (t.a != a) { if (visited[a][t.b - (a - t.a)][t.c] == 0) { que.add(new Node(a, t.b - (a - t.a), t.c, t.step + 1)); visited[a][t.b - (a - t.a)][t.c] = 1; } } } // c -> a if (t.c != 0) { if (t.a + t.c <= a) { if (visited[t.a + t.c][t.b][0] == 0) { que.add(new Node(t.a + t.c, t.b, 0, t.step + 1)); visited[t.a + t.c][t.b][0] = 1; } } else if (t.a != a) { if (visited[a][t.b][t.c - (a - t.a)] == 0) { que.add(new Node(a, t.b, t.c - (a - t.a), t.step + 1)); visited[a][t.b][t.c - (a - t.a)] = 1; } } } // b -> c if (t.b != 0) { if (t.b + t.c <= c) { if (visited[t.a][0][t.b + t.c] == 0) { que.add(new Node(t.a, 0, t.b + t.c, t.step + 1)); visited[t.a][0][t.b + t.c] = 1; } } else if (t.c != c) { if (visited[t.a][t.b - (c - t.c)][c] == 0) { que.add(new Node(t.a, t.b - (c - t.c), c, t.step + 1)); visited[t.a][t.b - (c - t.c)][c] = 1; } } } // c -> b if (t.c != 0) { if (t.c + t.b <= b) { if (visited[t.a][t.c + t.b][0] == 0) { que.add(new Node(t.a, t.c + t.b, 0, t.step + 1)); visited[t.a][t.c + t.b][0] = 1; } } else if (t.b != b) { if (visited[t.a][b][t.c - (b - t.b)] == 0) { que.add(new Node(t.a, b, t.c - (b - t.b), t.step + 1)); visited[t.a][b][t.c - (b - t.b)] = 1; } } } // a -> b if (t.a != 0) { if (t.a + t.b <= b) { if (visited[0][t.a + t.b][t.c] == 0) { que.add(new Node(0, t.a + t.b, t.c, t.step + 1)); visited[0][t.a + t.b][t.c] = 1; } } else if (t.b != b) { if (visited[t.a - (b - t.b)][b][t.c] == 0) { que.add(new Node(t.a - (b - t.b), b, t.c, t.step + 1)); visited[t.a - (b - t.b)][b][t.c] = 1; } } } // a -> c if (t.a != 0) { if (t.a + t.c <= c) { if (visited[0][t.b][t.a + t.c] == 0) { que.add(new Node(0, t.b, t.a + t.c, t.step + 1)); visited[0][t.b][t.a + t.c] = 1; } } else if (t.c != c) { if (visited[t.a - (c - t.c)][t.b][c] == 0) { que.add(new Node(t.a - (c - t.c), t.b, c, t.step + 1)); visited[t.a - (c - t.c)][t.b][c] = 1; } } } } System.out.println("NO"); } public static void main(String[] args) { while (in.hasNext()) { int a = in.nextInt(), b = in.nextInt(), c = in.nextInt(); if (a == 0 && b == 0 && c == 0) break; init(); bfs(a, b, c); } } } class Node { // a b c 代表实际拥有水的体积 int a, b, c, step; Node(int a, int b, int c, int step) { this.a = a; this.b = b; this.c = c; this.step = step; } }