http://acm.hdu.edu.cn/showproblem.php?pid=1495
个人意见,值得一看。
思路,总共6种倒水方式,把每种都倒一遍就行了,符合bfs。注意对已经倒过的情况保存记录,防止重复倒入。
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
int mm,nn,ss;
bool vis[105][105];
struct Node{
int m,n,s,t=0;
};
void msort(){
if(mm>nn){
int t=mm;
mm=nn;
nn=t;
}
if(nn>ss){
int t=nn;
nn=ss;
ss=t;
}
}
int main(){
while(cin>>ss>>nn>>mm&&ss!=0){
memset(vis,0,sizeof(vis));
msort();
if(ss%2==1){
cout<<"NO"<<endl;
continue;
}
Node n;
n.m=0;
n.n=0;
n.s=ss;
vis[0][0]=true;
queue<Node>q;
q.push(n);
bool flag=false;
while(!q.empty()){
Node node=q.front();
q.pop();
if(node.m==0&&node.n==node.s){
flag=true;
cout<<node.t<<"\n";
break;
}
//接下来就是倒水了
//6种倒水的方法
//m->n m->s n->m n->s s->m s->n
//倒水的原则: 看目标是不是满了,不满就倒
//倒水的结果,将倒水的容器的水全倒进去,
//如果目标的水大于容量, 倒水的容器为 差值
//否则,为零
//1 m->n
if(node.n<nn){
Node n1=node;
n1.n+=n1.m;
if(n1.n<=nn){
n1.m=0;
}else{
n1.m=n1.n-nn;
n1.n=nn;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
//2 m->s
if(node.s<ss){
Node n1=node;
n1.s+=n1.m;
if(n1.s<=ss){
n1.m=0;
}else{
n1.m=n1.s-ss;
n1.s=ss;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
//3 n->m
if(node.m<mm){
Node n1=node;
n1.m+=n1.n;
if(n1.m<=mm){
n1.n=0;
}else{
n1.n=n1.m-mm;
n1.m=mm;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
//4 n->s
if(node.s<ss){
Node n1=node;
n1.s+=n1.n;
if(n1.s<=ss){
n1.n=0;
}else{
n1.n=n1.s-ss;
n1.s=ss;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
//5 s->m
if(node.m<mm){
Node n1=node;
n1.m+=n1.s;
if(n1.m<=mm){
n1.s=0;
}else{
n1.s=n1.m-mm;
n1.m=mm;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
//6 s->n
if(node.n<nn){
Node n1=node;
n1.n+=n1.s;
if(n1.n<=nn){
n1.s=0;
}else{
n1.s=n1.n-nn;
n1.n=nn;
}
n1.t++;
if(!vis[n1.m][n1.n]){
vis[n1.m][n1.n]=true;q.push(n1);
}
}
}
if(!flag)cout<<"NO"<<endl;//有可能有 即使把所有情况遍历一遍也没有找到的元素。
}
return 0;
}