1 Problem Description
There are three cups, A, B and C, without calibration. The capacity is A, B and C respectively. How to measure the water with the capacity of K when only using these three cups?
Requirements: Water can be used indefinitely. Water in each cup can be poured out, refilled or poured into other cups.
2 state analysis
In terms of the amount of water in each cup, that is, the state node is represented by a triple (a, b, c), and there are (A+1)*(B+1)*(C+1) states. If the T2 state can be reached by one step pouring operation from T1 state, there is an edge between T1 and T2, which is recorded as T1 - > T2, thus a directed graph can be established.
For each state, there are at most 12 state transition rules as follows:
- If a > 0 => a=0; (pour out A cup of water)
- If b > 0 => b=0; (pour out B cup of water)
- If C > 0 => c=0; (pour out C cup of water)
import java.util.LinkedList; import java.util.Scanner; import java.util.Stack; class Status{ int a; int b; int c; Status(int a,int b,int c){ this.a=a; this.b=b; this.c=c; } } public class Main3 { static int A,B,C,K; static int[][][] dp; static int ans; static final int MAX=10000000; static Status[][][] plan; static LinkedList<Status> list=new LinkedList<Status>(); public static void main(String[] args) { Scanner sc=new Scanner(System.in); A=sc.nextInt(); B=sc.nextInt(); C=sc.nextInt(); K=sc.nextInt(); dp=new int[A+1][B+1][C+1]; plan=new Status[A+1][B+1][C+1]; for(int i=0;i<=A;i++) { for(int j=0;j<=B;j++) { for(int k=0;k<=C;k++) { dp[i][j][k]=MAX; plan[i][j][k]=new Status(0,0,0); } } } bfs(); Status status=choose(); print(status); } static void bfs() { dp[0][0][0]=0; plan[0][0][0]=null; list.add(new Status(0,0,0)); while(!list.isEmpty()) { Status sta=list.remove(); int a=sta.a; int b=sta.b; int c=sta.c; for(int i=0;i<12;i++) { Status s=change(a,b,c,i); if(s!=null) { list.add(s); } } } } static Status choose() { int a=0,b=0,c=0; ans=MAX; if(K<=C) { for(int i=0;i<=A;i++) { for(int j=0;j<=B;j++) { if(dp[i][j][K]<ans) { ans=dp[i][j][K]; a=i; b=j; c=K; } } } } if(K<=B) { for(int i=0;i<=A;i++) { for(int k=0;k<=C;k++) { if(dp[i][K][k]<ans) { ans=dp[i][K][k]; a=i; b=K; c=k; } } } } if(K<=A) { for(int j=0;j<=B;j++) { for(int k=0;k<=C;k++) { if(dp[K][j][k]<ans) { ans=dp[K][j][k]; a=K; b=j; c=k; } } } } return new Status(a,b,c); } static void print(Status status) { Stack<Status> stack=new Stack<Status>(); while(status!=null) { stack.add(status); int a=status.a; int b=status.b; int c=status.c; status=plan[a][b][c]; } while(!stack.isEmpty()) { status=stack.pop(); int a=status.a; int b=status.b; int c=status.c; if(stack.size()>0) System.out.print("("+a+","+b+","+c+")->"); else System.out.print("("+a+","+b+","+c+")"); } System.out.println("\n"+ans); } static Status change(int i,int j,int k,int s) { Status sta=new Status(i,j,k); switch(s) { case 0: //Empty A cup of water if(i>0) { if(dp[0][j][k]>dp[i][j][k]+1) { dp[0][j][k]=dp[i][j][k]+1; plan[0][j][k]=sta; return new Status(0,j,k); } } return null; case 1: //Empty B cup of water if(j>0) { if(dp[i][0][k]>dp[i][j][k]+1) { dp[i][0][k]=dp[i][j][k]+1; plan[i][0][k]=sta; return new Status(i,0,k); } } return null; case 2: //Empty C cup of water if(k>0) { if(dp[i][j][0]>dp[i][j][k]+1) { dp[i][j][0]=dp[i][j][k]+1; plan[i][j][0]=sta; return new Status(i,j,0); } } return null; case 3: //Fill up A glass of water if(i<A) { if(dp[A][j][k]>dp[i][j][k]+1) { dp[A][j][k]=dp[i][j][k]+1; plan[A][j][k]=sta; return new Status(A,j,k); } } return null; case 4: //Fill up B cups of water if(j<B) { if(dp[i][B][k]>dp[i][j][k]+1) { dp[i][B][k]=dp[i][j][k]+1; plan[i][B][k]=sta; return new Status(i,B,k); } } return null; case 5: //Fill up a C cup of water if(k<C) { if(dp[i][j][C]>dp[i][j][k]+1) { dp[i][j][C]=dp[i][j][k]+1; plan[i][j][C]=sta; return new Status(i,j,C); } } return null; case 6: //B->A if(j>0&&i<A) { if(i+j<=A) { if(dp[i+j][0][k]>dp[i][j][k]+1) { dp[i+j][0][k]=dp[i][j][k]+1; plan[i+j][0][k]=sta; return new Status(i+j,0,k); } }else { if(dp[A][i+j-A][k]>dp[i][j][k]+1) { dp[A][i+j-A][k]=dp[i][j][k]+1; plan[A][i+j-A][k]=sta; return new Status(A,i+j-A,k); } } } return null; case 7: //C->A if(k>0&&i<A) { if(i+k<=A) { if(dp[i+k][j][0]>dp[i][j][k]+1) { dp[i+k][j][0]=dp[i][j][k]+1; plan[i+k][j][0]=sta; return new Status(i+k,j,0); } }else { if(dp[A][j][i+k-A]>dp[i][j][k]+1) { dp[A][j][i+k-A]=dp[i][j][k]+1; plan[A][j][i+k-A]=sta; return new Status(A,j,i+k-A); } } } return null; case 8: //A->B if(i>0&&j<B) { if(i+j<=B) { if(dp[0][i+j][k]>dp[i][j][k]+1) { dp[0][i+j][k]=dp[i][j][k]+1; plan[0][i+j][k]=sta; return new Status(0,i+j,k); } }else { if(dp[i+j-B][B][k]>dp[i][j][k]+1) { dp[i+j-B][B][k]=dp[i][j][k]+1; plan[i+j-B][B][k]=sta; return new Status(i+j-B,B,k); } } } return null; case 9: //C-B if(k>0&&j<B) { if(j+k<=B) { if(dp[i][j+k][0]>dp[i][j][k]+1) { dp[i][j+k][0]=dp[i][j][k]+1; plan[i][j+k][0]=sta; return new Status(i,j+k,0); } }else { if(dp[i][B][j+k-B]>dp[i][j][k]+1) { dp[i][B][j+k-B]=dp[i][j][k]+1; plan[i][B][j+k-B]=sta; return new Status(i,B,j+k-B); } } } return null; case 10: //A->C if(i>0&&k<C) { if(i+k<=C) { if(dp[0][j][i+k]>dp[i][j][k]+1) { dp[0][j][i+k]=dp[i][j][k]+1; plan[0][j][i+k]=sta; return new Status(0,j,i+k); } }else { if(dp[i+k-C][j][C]>dp[i][j][k]+1) { dp[i+k-C][j][C]=dp[i][j][k]+1; plan[i+k-C][j][C]=sta; return new Status(i+k-C,j,C); } } } return null; case 11: //B->C if(j>0&&k<C) { if(j+k<=C) { if(dp[i][0][j+k]>dp[i][j][k]+1) { dp[i][0][j+k]=dp[i][j][k]+1; plan[i][0][j+k]=sta; return new Status(i,0,j+k); } }else { if(dp[i][j+k-C][C]>dp[i][j][k]+1) { dp[i][j+k-C][C]=dp[i][j][k]+1; plan[i][j+k-C][C]=sta; return new Status(i,j+k-C,C); } } } return null; } return null; } }