【题意】可乐体积s=n+m,n和m是另外两个杯子的体积,只能用可乐瓶和这两个杯子来回倾倒,而且上面没有刻度。问至少需要倒几次才能实现可乐的平分,如果不能实现,输出"NO".输入为0 0 0时结束。
【广度优先搜索总结】
1.状态。我们要确定求解问题中的状态
2.状态扩展方式
3.有效状态
4.队列
5.标记
6.有效状态数
7.最优
【输入输出】
7 4 3
NO
4 1 3
3
【注意】1.队列实现,注意每次队列要清空 2.Q.front( ) 3.如果s的体积是奇数,则不可能实现平分(因为瓶子的体积都是整数)
【代码】
#include<iostream>
#include<cstring>
#include<vector>
#include<math.h>
#include<algorithm>
#include<queue>
using namespace std;
#define maxi 0x3f3f3f3f
struct state
{
int v1,v2,v3,t;
};
queue<state> Q;
int mark[102][102][102];
void atob(int &a,int va,int &b,int vb)
{
if(a+b<=vb)
{
b=a+b;
a=0;
}
else
{
a=a-(vb-b);
b=vb;
}
}
int main(int argc, char const *argv[])
{
int s,n,m;
bool flag=true;
while(cin>>s)
{
cin>>n>>m;
if(s==n&&n==m&&n==0)break;
memset(mark,false,sizeof(mark));
int right=s/2;
if(right%2==1)
{
cout<<"NO"<<endl;
continue;
}
state p;
p.v1=s;
p.v2=0;
p.v3=0;
p.t=0;
mark[s][0][0]=true;
Q.push(p);
while(!Q.empty())
{
state now=Q.front();
Q.pop();
int v1,v2,v3;
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v1,s,v2,n);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v2,n,v1,s);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v2,n,v3,m);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v3,m,v2,n);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v1,s,v3,m);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
v1=now.v1;
v2=now.v2;
v3=now.v3;
atob(v3,m,v1,s);
if(mark[v1][v2][v3]==false)
{
if(v1==right&&v2==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v2==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
if(v1==right&&v3==right)//别忘了判断有三组
{
cout<<now.t+1<<endl;
flag=false;
break;
}
state temp;
temp.v1=v1;
temp.v2=v2;
temp.v3=v3;
temp.t=now.t+1;
Q.push(temp);
mark[v1][v2][v3]=true ;
}
}
if(flag)cout<<"NO"<<endl;
while(!Q.empty())Q.pop();
}
return 0;
}