NYOJ--21(搜索)-题目-----------------------------三个水杯

来源:互联网 发布:绝对领域 知乎 编辑:程序博客网 时间:2024/04/20 10:34
package search;/*三个水杯 时间限制:1000 ms  |  内存限制:65535 KB 描述 给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。 三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。 现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。 输入 第一行一个整数N(0<N<50)表示N组测试数据 接下来每组测试数据有两行,第一行给出三个整数V1 V2 V3 (V1>V2>V3 V1<100 V3>0)表示三个水杯的体积。 第二行给出三个整数E1 E2 E3 (体积小于等于相应水杯体积)表示我们需要的最终状态 输出 每行输出相应测试数据最少的倒水次数。如果达不到目标状态输出-1 样例输入 2 6 3 1 4 1 1 9 3 2 7 1 1 样例输出 3 -1 我的思路:这道题和我做的拿到泊松分酒感觉挺像的,但是我那样做,不能保证是最少次数的,然后又用深搜,不知道为什么一直内存益处; 最后实在不知道咋办,就找度娘,看了一大神(http://blog.csdn.net/jcjc918/article/details/9336785)的思路,然后我用java做出来了。用广搜。 首先杯子有三个:a , b ,c; 1,先将杯子a放进队列,在bfs()里,出队,那么a可以给b或者c倒水,那就分别都倒水 2,上一步完成之后,就将b和c的状态入队,同时用一个数组记录那个状态出现过了就为true 3,不断重复1,2步骤,直到队列为空为止,请看代码。 */import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.Scanner;import java.util.Arrays;import java.util.LinkedList;public class search_21 {// 创建一个杯子类public static class Cup {int a, b, c, count;public Cup() {}public Cup(int a, int b, int c) {this.a = a;this.b = b;this.c = c;}}private static int v1 = 0, v2 = 0, v3 = 0, e1 = 0, e2 = 0, e3 = 0;// 一开始输入的杯子体积和目标状态private static LinkedList<Cup> cups = new LinkedList<Cup>();// 队列private static boolean[][][] visited = new boolean[101][101][101];// 记录杯子出现过的状态private static Cup start, cup;private static boolean has;// 判断是否有可能达到目标状态public static void main(String[] args) {Scanner sc = new Scanner(new BufferedReader(new InputStreamReader(System.in)));int n = sc.nextInt();while (n-- > 0) {// 这里是初始化,因为题目要求可一次同时测试多组数据cups.clear();for (int i = 0; i < 101; i++)for (int j = 0; j < 101; j++)Arrays.fill(visited[i][j], false);has = false;v1 = sc.nextInt();v2 = sc.nextInt();v3 = sc.nextInt();e1 = sc.nextInt();e2 = sc.nextInt();e3 = sc.nextInt();start = new Cup(v1, 0, 0);visited[v1][0][0] = true;cups.add(start);// 将初始状态入队bfs();// 广搜if (!has)System.out.println(-1);}sc.close();}private static void bfs() {while (!cups.isEmpty()) {cup = cups.remove();// 出队// System.out.println(cup.a + " " + cup.b + " " +// cup.c);//打印过程// 如果达到目标if (cup.a == e1 && cup.b == e2 && cup.c == e3) {System.out.println(cup.count);has = true;break;}// 如果杯子a有水,而杯子b的水没有符合目标要求,那么a倒水给bif (cup.a != 0 && cup.b < v2) {Cup tmp = new Cup();// 如果a的水+b的水比b的水杯体积还大,那么a杯子有剩if (cup.a + cup.b > v2)tmp.a = cup.a + cup.b - v2;elsetmp.a = 0;// 那么b杯子有a倒过来的水( cup.a - tmp.a )+可能自己原本也有的水(cup.b)tmp.b = cup.a - tmp.a + cup.b;tmp.c = cup.c;tmp.count = cup.count + 1;// 更新次数// 标记状态if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}//下面一样的道理//a→cif (cup.a != 0 && cup.c < v3) {Cup tmp = new Cup();if (cup.a + cup.c > v3)tmp.a = cup.a + cup.c - v3;elsetmp.a = 0;tmp.c = cup.a - tmp.a + cup.c;tmp.b = cup.b;tmp.count = cup.count + 1;if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}//b→aif (cup.b != 0 && cup.a < v1) {Cup tmp = new Cup();if (cup.b + cup.a > v1)tmp.b = cup.b + cup.a - v1;elsetmp.b = 0;tmp.a = cup.b - tmp.b + cup.a;tmp.c = cup.c;tmp.count = cup.count + 1;if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}//b→cif (cup.b != 0 && cup.c < v3) {Cup tmp = new Cup();if (cup.b + cup.c > v3)tmp.b = cup.b + cup.c - v3;elsetmp.b = 0;tmp.c = cup.b - tmp.b + cup.c;tmp.a = cup.a;tmp.count = cup.count + 1;if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}//c→aif (cup.c != 0 && cup.a < v1) {Cup tmp = new Cup();if (cup.c + cup.a > v1)tmp.c = cup.c + cup.a - v1;elsetmp.c = 0;tmp.a = cup.c - tmp.c + cup.a;tmp.b = cup.b;tmp.count = cup.count + 1;if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}//c→bif (cup.c != 0 && cup.b < v2) {Cup tmp = new Cup();if (cup.c + cup.b > v2)tmp.c = cup.c + cup.b - v2;elsetmp.c = 0;tmp.b = cup.c - tmp.c + cup.b;tmp.a = cup.a;tmp.count = cup.count + 1;if (!visited[tmp.a][tmp.b][tmp.c]) {visited[tmp.a][tmp.b][tmp.c] = true;cups.add(tmp);}}}}}

0 0
原创粉丝点击