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

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

2014年12月21日 22:26:46

阅读数:1278

题目描述:
转载地址https://blog.csdn.net/fool_ran/article/details/42065653

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

输入

第一行一个整数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代码:

 
  1.  
    /**
     *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;
    }
    

猜你喜欢

转载自blog.csdn.net/Strive_Y/article/details/81813041