题目描述:
http://acm.nyist.net/JudgeOnline/problem.php?pid=21
2
6 3 1
4 1 1
9 3 2
7 1 1
3
-1
题目分析:
经典题目,bfs搜索,不用回溯,直接暴力即可。
AC代码:
/**
*bfs,隐式图的搜索
*/
#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<cmath>
using namespace std;
int vis[101][101][101];//记录是否被访问
struct StateNode{
int cur[3];//记录当前状态
int v[3];//记录状态
int step;//步数
};
queue<StateNode> q;
int Sucess(StateNode a,StateNode b){//比较是否相等
return (a.cur[0] == b.cur[0] && a.cur[1] == b.cur[1] && a.cur[2] == b.cur[2]);
}
int main()
{
int t,res;
StateNode b,e;
cin>>t;
while(t--){
res=-1;
while(!q.empty()){//清空队列
q.pop();
}
cin>>b.v[0]>>b.v[1]>>b.v[2];
//下面开始模拟倒水,并搜索
b.cur[0]=b.v[0];//首先先给最大的水杯倒满水
b.cur[1]=b.cur[2]=0;//小杯子为0
b.step=0;//记录步数
cin>>e.cur[0]>>e.cur[1]>>e.cur[2];
int ok=0;//记录是否可以到达结尾状态
memset(vis,0,sizeof(vis));
q.push(b);//加入队列
vis[b.cur[0]][b.cur[1]][b.cur[2]]=1;//已经在访问或者已经访问
while(!q.empty()){//进行广搜
StateNode u=q.front();
//cout<<u.cur[0]<<" "<<u.cur[1]<<" "<<u.cur[2]<<endl;
q.pop();
if(Sucess(u,e)){//成功并结束
res=u.step;
break;
}
//else 模拟倒水
for(int i=0;i<=2;i++){//用每一个被子给其他两个被子倒水
for(int j=0;j<=2;j++){
if(i!=j){
int minv=u.v[j]-u.cur[j];//从当前状态到被子倒满,需要的水
if(u.cur[i]<minv){//当前的水小于需要的水,则能用的水变为当前的水
minv=u.cur[i];
}
//出现新节点
StateNode v=u;
v.cur[i]-=minv;//必须先减去
v.cur[j]+=minv;
v.step=u.step+1;//更新步数
//cout<<u.step<<endl;
if(!vis[v.cur[0]][v.cur[1]][v.cur[2]]){//该结点没有被访问
q.push(v);//加入队列
vis[v.cur[0]][v.cur[1]][v.cur[2]]=1;//已访问
}
}
}
}
}
cout<<res<<endl;
}
return 0;
}
原文地址:http://blog.csdn.net/fool_ran/article/details/42065653