首页 > 代码库 > NYOJ21 三个水杯 (经典问题 bfs)

NYOJ21 三个水杯 (经典问题 bfs)

题目描述:
http://acm.nyist.net/JudgeOnline/problem.php?pid=21

给出三个水杯,大小不一,并且只有最大的水杯的水是装满的,其余两个为空杯子。三个水杯之间相互倒水,并且水杯没有标识,只能根据给出的水杯体积来计算。现在要求你写出一个程序,使其输出使初始状态到达目标状态的最少次数。
输入
第一行一个整数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

题目分析:

经典题目,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;
}
        



NYOJ21 三个水杯 (经典问题 bfs)