NYOJ21 三个水杯


三个水杯

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数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



import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Scanner;
/**
 * 广度优先搜索
 * @author Administrator
 *
 */
public class n021_三个水杯 {
	
	public static void main(String[] args) {
	
		int[][] nn=getInput();
		for(int i=0;i<nn.length;i++){
			System.out.println(f(nn[i]));
		}
		
	}
	
	public static int f(int[] nn){
		//倒水次数
		int num=0;
		//杯子体积
		int[] volumes=new int[3];
		//目标状态
		int[] goal=new int[3];
		//当前状态
		int[] state=new int[3];
		//下一次倒水可能出现的所有状态
		ArrayList<int[]> temp=new ArrayList<int[]>();
		//历史记录
		ArrayList<int[]> history=new ArrayList<int[]>();
		//初始化
		for(int i=0;i<goal.length;i++){
			volumes[i]=nn[i];
			goal[i]=nn[i+3];
		}
		state[0]=volumes[0];
		temp.add(state.clone());
		history.add(state.clone());
		//
		while(temp.size()>0){
			
			if(check(temp,goal)){
				return num;
			}
			ArrayList<int[]> temp_n=new ArrayList<int[]>();
			Iterator<int[]> it=temp.iterator();
			while(it.hasNext()){
				state=it.next();
				for(int i=0;i<3;i++){
					if(state[i]==0) continue;
					for(int j=0;j<3;j++){
						if(j==i||state[j]==volumes[j]) continue;
						int[] t=state.clone();
						if(t[i]-volumes[j]+t[j]>0){
							t[i]=t[i]-volumes[j]+t[j];
							t[j]=volumes[j];
						}else{
							t[j]+=t[i];
							t[i]=0;
						}
						if(!check(history,t)){
							temp_n.add(t);
							history.add(t);
						}
					}
				}
			}
			temp=temp_n;
			num++;
		}
	
		return -1;
	}
	
	/**
	 * 是否存在目标状态
	 * @param temp 状态的集合 
	 * @param goal 目标状态
	 * @return 
	 */
	public static boolean check(ArrayList<int[]> temp,int[] goal){
		for(int i=0;i<temp.size();i++){
			if(Arrays.equals(temp.get(i), goal))
				return true;
		}
		return false;
	}
	/**
	 * 接收输入
	 */
	public static int[][] getInput(){
		
		Scanner scan=new Scanner(System.in);
		int N=scan.nextInt();
		int[][] nn=new int[N][6];
		//0 1 2  分别存放水杯容量
		//3 4 5  分别存放目标状态
		for(int i=0;i<N;i++){
			for(int j=0;j<nn[i].length;j++){
				nn[i][j]=scan.nextInt();
			}
		}
		return nn;
	}
}

原题链接: http://acm.nyist.net/JudgeOnline/problem.php?pid=21

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值