hdu1495 && pku3414

题意:

大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
分析:直接搜索+模拟
对于N和M俩个杯子的当前状态,每次都有俩种选择,S->N,S->M,N->S,N->M,M->S,M->N
用了BFS和DFS 个写了一个,写dfs的时候,开了个全局Debug了半天,ORZ
BFS版
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
bool vis[110][110];
short S,N,M,s,n,m;
int ans;
struct state
{
	short n,m;
	short cnt;
	state(short a=0,short b=0,short c=0):n(a),m(b),cnt(c){} 
};
queue<state> Q;
void BFS()
{
	Q.push(state(0,0,0));
	vis[0][0]=true;
	state tmp;
	while(!Q.empty())
	{
	    tmp=Q.front();
		Q.pop();
		if((tmp.n==S/2 || tmp.m==S/2)&&(S-(tmp.n+tmp.m))==S/2)
		{
			ans=tmp.cnt;
			return ;
		}
	    s=S-tmp.n-tmp.m,n=tmp.n,m=tmp.m;
		if(s!=0)
		{
			if(s+n>=N)
			{
				s-=(N-n);
				n=N;
			}
			else {
				n+=s;
				s=0;
			}
			if(!vis[n][S-s-n]){
				Q.push(state(n,S-s-n,tmp.cnt+1));
				vis[n][S-s-n]=true;
			}
			s=S-tmp.n-tmp.m,n=tmp.n,m=tmp.m;
			if(s+m>=M)
			{
				s-=(M-m);
				m=M;
			}
			else m+=s,s=0;
			if(!vis[S-s-m][m]){
				Q.push(state(S-s-m,m,tmp.cnt+1));
				vis[S-s-m][m]=true;
			}
		}
		s=S-tmp.n-tmp.m,n=tmp.n,m=tmp.m;
		if(n!=0)
		{
			if(!vis[0][m]){
				Q.push(state(0,m,tmp.cnt+1));
				vis[0][m]=true;
			}
			if(n+m>=M)
			{
				n-=(M-m);
				m=M;
			}
			else m+=n,n=0;
			if(!vis[n][m]){
				Q.push(state(n,m,tmp.cnt+1));
				vis[n][m]=true;
			}
		}
		s=S-tmp.n-tmp.m,n=tmp.n,m=tmp.m;
		if(m!=0)
		{
			if(!vis[n][0]){
				Q.push(state(n,0,tmp.cnt+1));
				vis[n][0]=true;
			}
			if(m+n>=N)
			{
				m-=(N-n);
				n=N;
			}
			else n+=m,m=0;

			if(!vis[n][m]){
				Q.push(state(n,m,tmp.cnt+1));
				vis[n][m]=true;
			}
		}
	}
}
int main()
{
	while(scanf("%d %d %d",&S,&N,&M)==3 && (S||N||M))
	{
		if(S%2!=0)
		{
			puts("NO");
			continue;
		}
		memset(vis,false ,sizeof(vis));
		while(!Q.empty())
			Q.pop();
		ans=-1;
		BFS();
		if(ans==-1)
			puts("NO");
		else printf("%d\n",ans);
	}
}


DFS版

#include<iostream>
const int inf=0x7fffffff;
const int MAX=105;
using namespace std;
int ans;
int S,N,M;
bool vis[MAX][MAX];
void dfs(int a,int b,int cnt)
{
//	cout<<"check"<<vis[0][3]<<endl;
	if((a==S/2||b==S/2) && (S-(a+b))==S/2)
	{
	//	cout<<a<<' '<<b<<endl;
		if(ans>cnt)
			ans=cnt;
		return ;
	}
	 int   s=S-a-b,n=a,m=b;
		if(s!=0)
		{
			if(s+n>=N)
			{
				s-=(N-n);
				n=N;
			}
			else n+=s,s=0;
			if(!vis[n][m]){
				vis[n][m]=1;
		//		cout<<"S->n"<<endl;
				dfs(n,m,cnt+1);
				vis[n][m]=0;
		//		cout<<"fan1 "<<n<<' '<<m<<' '<<vis[n][m]<<endl;
			}
			s=S-a-b,n=a,m=b;
			if(s+m>=M)
			{
				s-=(M-m);
				m=M;
			}
			else m+=s,s=0;
		//	printf("%d    %d\n",n,m);
		//	cout<<cnt<<endl;
		//	cout<<vis[n][m]<<endl;
			if(!vis[n][m]){
				vis[n][m]=1;
		//		cout<<"S->m"<<endl;
				dfs(n,m,cnt+1);
				vis[n][m]=0;
		//		cout<<"fan2 "<<n<<' '<<m<<' '<<vis[n][m]<<endl;
			}
		}
		s=S-a-b,n=a,m=b;
		if(n!=0)
		{
			if(!vis[0][m]){
				vis[0][m]=1;
		//		cout<<"N->S"<<endl;
				dfs(0,m,cnt+1);
				vis[0][m]=0;
		//		cout<<"fan3 "<<0<<' '<<m<<' '<<vis[0][m]<<endl;
			}
			if(n+m>=M)
			{
				n-=(M-m);
				m=M;
			}
			else m+=n,n=0;
			if(!vis[n][m]){
				vis[n][m]=1;
		//		cout<<"N->m"<<endl;
				dfs(n,m,cnt+1);
				vis[n][m]=0;
		//		cout<<"fan4 "<<n<<' '<<m<<' '<<vis[n][m]<<endl;
			}
		}
		s=S-a-b,n=a,m=b;
		if(m!=0)
		{
			if(!vis[n][0]){
				vis[n][0]=1;
			//	cout<<"m->s"<<endl;
				dfs(n,0,cnt+1);
				vis[n][0]=0;
			//	cout<<"fan5 "<<n<<' '<<m<<' '<<vis[n][0]<<endl;
			}
			if(m+n>=N)
			{
				m-=(N-n);
				n=N;
			}
			else n+=m,m=0;
			if(!vis[n][m]){
				vis[n][m]=1;
			//	cout<<"m->n"<<endl;
				dfs(n,m,cnt+1);
				vis[n][m]=0;
			//	cout<<"fan6 "<<n<<' '<<m<<' '<<vis[n][m]<<endl;
			}
		}
}
int main(void)
{
	while(scanf("%d %d %d",&S,&N,&M)==3&& (S||N||M))
	{
		
		if(S%2!=0)
		{
			puts("NO");
			continue;
		}
		memset(vis,0,sizeof(vis));
		ans=inf;
		vis[0][0]=1;
		dfs(0,0,0);
		if(ans==inf)
			puts("NO");
		else printf("%d\n",ans);
	}
	return 0;
}

 这是PKU上面一道类似的题目的代码,不同的是,这题目要求保存路径

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
struct state
{
	int a,b;
	string road;
	state(int x=0,int y=0,string str=""):a(x),b(y),road(str){}
};
//A : drop A
//B : drop B
//C : A to B
//D : B to A
//E : fill A
//F " fill B
queue<state> Q;
int vis[101][101],A,B,C;
bool success;
string ans;
void BFS()
{
	success=false;
	Q.push(state(0,0,""));
	memset(vis,false,sizeof(vis));
	vis[0][0]=true;
	while(!Q.empty())
	{
		state temp=Q.front();
		string str=temp.road;
		Q.pop();
		int a=temp.a,b=temp.b,a1,b1;
		if(a==C || b==C)
		{
			success=true;
			ans=temp.road;
			return ;
		}
		if(a!=0 && !vis[0][b])
		{
			vis[0][b]=true;
			Q.push(state(0,b,(str + "A")));
		}
		if(b!=0 && !vis[a][0])
		{
			vis[a][0]=true;
			Q.push(state(a,0,(str + "B")));
		}
		if(a!=0 && b!=B)
		{
			if(a+b<B)
			{
				b1=a+b;
				a1=0;
			}
			else {
				b1=B;
				a1=a+b-B;
			}
			if(!vis[a1][b1])
			{
				vis[a1][b1]=true;
				Q.push(state(a1,b1,(str+"C")));
			}
		}
		if(a!=A && b!=0)
		{
			if(a+b<A)
			{
				a1=a+b;
				b1=0;
			}
			else a1=A,b1=a+b-A;
			if(!vis[a1][b1])
			{
				vis[a1][b1]=true;
				Q.push(state(a1,b1,(str+"D")));
			}
		}
		if(a!=A && !vis[A][b])
		{
			vis[A][b]=true;
			Q.push(state(A,b,(str+"E")));
		}
		if(b!=B && !vis[a][B])
		{
			vis[a][B]=true;
			Q.push(state(a,B,(str+"F")));
		}
	}
}
int main()
{
	while(scanf("%d %d %d",&A,&B,&C)==3)
	{
		while(!Q.empty())
			Q.pop();
		BFS();
		if(!success)
		{
			puts("impossible");
			continue;
		}
		//cout<<ans<<endl;
		int len=ans.length();
		printf("%d\n",len);
		for(int i=0;i<len;i++)
		{
			if(ans[i]=='A')
				puts("DROP(1)");
			else if(ans[i]=='B')
				puts("DROP(2)");
			else if(ans[i]=='C')
				puts("POUR(1,2)");
			else if(ans[i]=='D')
				puts("POUR(2,1)");
			else if(ans[i]=='E')
				puts("FILL(1)");
			else puts("FILL(2)");
		}
	}
	return 0;
}

 

posted @ 2011-11-26 14:51  枕边梦  阅读(243)  评论(0编辑  收藏  举报