1. 程式人生 > >1117-三個水杯

1117-三個水杯

1117 - 三個水杯

時間限制:1秒 記憶體限制:128兆

題目描述

給出三個水杯,大小不一,並且只有最大的水杯的水是裝滿的,其餘兩個為空杯子。三個水杯之間相互倒水,並且水杯沒有標識,只能根據給出的水杯體積來計算。現在要求你寫出一個程式,使其輸出使初始狀態到達目標狀態的最少次數。

輸入

第一行一個整數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

 

三個水杯問題其實就是對水杯裡面的水進行互相倒的過程,我們可以用三維陣列來標記每一次倒水後的狀態,如果在倒水後發現之前出現過這個狀態,那麼就說明此時已經重複操作了,return出去就好

下面是dfs暴力程式碼

#include<stdio.h>
#include<string.h>
int zt[105][105][105];
int sa,sb,sc;
int flag,step;
int ea,eb,ec;
void dfs(int a,int b, int c,int num)
{
	if(flag==1&&num>step)//如果所需次數大於之前成功狀態時的次數,返回上一步操作 
	return ;
	if(a==ea&&b==eb&&c==ec)//滿足最終狀態條件,進行判斷 
	{
		if(step==0)//第一次的成功狀態 
		step=num;
		else//不止一次能夠達到成功狀態 
		{
			if(step>num)
			step=num;
		}
		flag=1;
		return ;
	}
	for(int i=1;i<=6;i++)
	{
		if(i==1)//a向b倒水 
		{
			if(a>sb-b&&b!=sb)//a水杯向b水杯倒水,能將b水杯倒滿的情況 
			{
				int x=b;
				a=a-sb+x;
				b=sb;
				if(zt[a][b][c]==1)
				{
					b=x;
					a=a-x+sb;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				b=x;
				a=a-x+sb;
			}
			else//a向b倒水,把a水杯倒空的情況 
			{
				if(a!=0)
				{
					int x=a;
					b=b+x;
					a=0;
					if(b<=sb)
					{
						if(zt[a][b][c]==1)
						{
							a=x;
							b=b-x;
							continue ;
						}
						zt[a][b][c]=1;
						dfs(a,b,c,num+1);
						zt[a][b][c]=0;
					}
					a=x;
					b=b-x;
				}	
			}
		}
		if(i==2)//a向c倒水 
		{
			if(a>sc-c&&c!=sc) //將c倒滿 
			{
				int x=c;
				a=a-sc+c;
				c=sc;
				if(zt[a][b][c]==1)
				{
					a=a-x+sc;
					c=x;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				a=a-x+sc;
				c=x;
			}
			else//將a倒空 
			{
				if(a!=0)
				{
					int x=a;
					c=c+a;
					a=0;
					if(c<=sc)
					{
						if(zt[a][b][c]==1)
						{
							a=x;
							c=c-x;
							continue ;
						}
						zt[a][b][c]=1;
						dfs(a,b,c,num+1);
						zt[a][b][c]=0;
					}	
					a=x;
					c=c-x;
				}	
			}
		}
		if(i==3)//b向a倒水 
		{
			if(b<sa-a)//將b倒空 
			{
				if(b!=0)
				{
					int x=b;
					a=a+b;
					b=0;
					if(a<=sa)
					{
						if(zt[a][b][c]==1)
						{
							b=x;
							a=a-x;
							continue ;
						}
						zt[a][b][c]=1;
						dfs(a,b,c,num+1);
						zt[a][b][c]=0;
					}
					b=x;
					a=a-x;
				}
				
			}
			else//將a倒滿 
			{
				int x=a;
				b=b-sa+a;
				a=sa;
				if(zt[a][b][c]==1)
				{
					a=x;
					b=b-x+sa;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				a=x;
				b=b-x+sa;
			}
		}
		if(i==4)//b向c倒水 
		{
			if(b>sc-c&&c!=sc)//將c倒滿 
			{
				int x=c;
				b=b-sc+c;
				c=sc;
				if(zt[a][b][c]==1)
				{
					b=b-x+sc;
					c=x;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				b=b-x+sc;
				c=x;
			}
			else//將b倒空 
			{
				if(b!=0)
				{
					int x=b;
					c=c+b;
					b=0;
					if(c<=sc)
					{
						if(zt[a][b][c]==1)
						{
							b=x;
							c=c-x;
							continue ;
						}
						zt[a][b][c]=1;
						dfs(a,b,c,num+1);
						zt[a][b][c]=0;
					}
					b=x;
					c=c-x;
				}
				
			}
		}
		if(i==5)//c向a倒水 
		{
			if(c>sa-a&&a!=sa)//將a倒滿 
			{
				int x=a;
				c=c-sa+a;
				a=sa;
				if(zt[a][b][c]==1)
				{
					c=c-x+sa;
					a=x;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				c=c-x+sa;
				a=x;
			}
			else//將c倒空 
			{
				if(c!=0)
				{
					int x=c;
					a=a+c;
					c=0;
					if(zt[a][b][c]==1)
					{
						a=a-x;
						c=x;
						continue ;	
					}
					zt[a][b][c]=1;
					dfs(a,b,c,num+1);
					zt[a][b][c]=0;
					a=a-x;
					c=x;
				}
			}
		}
		if(i==6)//c向b倒水 
		{
			if(c>sb-b&&b!=sb)//將b倒滿 
			{
				int x=b;
				c=c-sb+b;
				b=sb;
				if(zt[a][b][c]==1)
				{
					b=x;
					c=c-x+sb;
					continue ;
				}
				zt[a][b][c]=1;
				dfs(a,b,c,num+1);
				zt[a][b][c]=0;
				b=x;
				c=c-x+sb;
			}
			else//將c倒空 
			{
				int x=c;
				b=b+c;
				c=0;
				if(b<=sb)
				{
					if(zt[a][b][c]==1)
					{
						c=x;
						b=b-x;
						continue ;
					}
					zt[a][b][c]=1;
					dfs(a,b,c,num+1);
					zt[a][b][c]=0;
				}
				c=x;
				b=b-x;
			}
		}
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d %d %d",&sa,&sb,&sc);
		scanf("%d %d %d",&ea,&eb,&ec);
		if(sa==ea&&eb==0&&ec==0)
		printf("0\n");
		else
		{
			zt[sa][0][0]=1;
			dfs(sa,0,0,0);
			if(step!=0)
			printf("%d\n",step);
			if(step==0)
			printf("-1\n");
		}
		step=0;
		flag=0;
		memset(zt,0,sizeof(zt));	
	}
}

以下為向xzl借鑑的bfs程式碼,思路是一樣的,程式碼中不再做說明

#include<iostream>
#include<queue>
#include<string.h>
using namespace std;
int v1,v2,v3;
int e1,e2,e3;
struct Node
{
	int x,y,z,step;
	Node(){}
	Node(int xx,int yy,int zz,int ss) : x(xx) , y(yy) , z(zz) ,step(ss) {} 
};
int book[110][110][110];
int bfs(int x,int y,int z,int ss)
{
	memset(book,0,sizeof(book));
	queue<Node> Q;
	Q.push(Node(x,y,z,ss));
	book[x][y][z] = 1 ;
	while(!Q.empty())
	{
		Node u = Q.front();
		Q.pop();
		if(u.x==e1&&u.y==e2&&u.z==e3)
		{
			return u.step ; 
		}
		for(int i = 0 ; i < 6 ; i++)
		{
			Node s = u ;
			if(i == 0 ) // a - b
			{
				int  minn = min(s.x , v2 - s.y);
				s.x-=minn;
				s.y+=minn;
			}
			if(i == 1 ) // a - c
			{
				int  minn = min(s.x , v3 - s.z);
				s.x-=minn;
				s.z+=minn;
			} 
			if(i == 2 ) // b - a
			{
				int  minn = min(s.y , v1 - s.x);
				s.x+=minn;
				s.y-=minn;
			} 
			if(i == 3 ) // b - c
			{
				int  minn = min(s.y , v3 - s.z);
				s.z+=minn;
				s.y-=minn;
			} 
			if(i == 4 ) // c - b
			{
				int  minn = min(s.z , v2 - s.y);
				s.z-=minn;
				s.y+=minn;
			}
			if(i == 5 ) // c - a
			{
				int  minn = min(s.z , v1 - s.x);
				s.x+=minn;
				s.z-=minn;
			} 
			int sss = u.step + 1 ;
			if(book[s.x][s.y][s.z] == 0)
			{
				Q.push(Node(s.x,s.y,s.z,sss));
				book[s.x][s.y][s.z] = 1 ;
			}
		}
	}
	return -1;
}
int main()
{
	int n;
	scanf("%d",&n); 
	while(n--)
	{
		scanf("%d %d %d",&v1,&v2,&v3);
		scanf("%d %d %d",&e1,&e2,&e3);
		int ans = bfs(v1 , 0, 0 ,0);
		printf("%d\n",ans);
	}
}