zoj1005(广度优先搜索)

题目链接:zoj1005;

这道题是我第一次用广度优先搜索。虽然之前就知道BFS是怎么回事,但是没在具体题目上用过,所以相比DFS,感觉相对生疏。

(虽然这道题网上看到可以用数学方法,很轻松解出;但是为了挑战一下BFS,我还是决定死磕一下)

这道题我看完第一个念头就是搜索。因为每一步就是那几个有限的选择。(虽然题目没说,但是我还是求了最少步骤解出答案的方案,毕竟这种题答案是不唯一的)——考虑到这一点,所以这道题更适合广度优先搜索。

下面是代码(注释比较详细):

#include<bits/stdc++.h>
#include<queue>
using namespace std;

int va,vb,n;
int vis[1000][1000];
struct state
{
    int a;
    int b;
    string way;
};
queue <state> que;
string ope[7]= {"fill A", "fill B","empty A","empty B", "pour A B","pour B A","success"};
int main()
{
    while(cin>>va>>vb>>n)
    {

        memset(vis,0,sizeof(vis));
        while(!que.empty())
            que.pop();      //初始化操作


        state start= {0,0,""};  //表示最开始的时候两个罐子都为空
        vis[0][0]=1;            //vis[i][j]表示a=i且b=j这个状态之前是否经历过,避免重复操作

        struct state current,next;//定义两个状态,分别为当前状态和下一个状态

        que.push(start);

        while(!que.empty())
        {

            current=que.front();
            que.pop();
        //    cout<<current.a<<"www"<<endl;

            if(current.b==n)      //当b罐子中的水已经达到n的时候,停止bfs
            {
                //输出
               // cout<<"ppppp"<<endl;
                for(int i=0;i<current.way.length();i++){
                    cout<<ope[(int)(current.way[i]-'0')]<<endl;
                }
                cout<<ope[6]<<endl;
                break;
            }
            else
            {
                next=current;

                if(current.a<va) //如果当前状态a罐子没满
                {
                   //  cout<<"000"<<endl;
                    next.a=va;
                    next.b=current.b;
                    next.way=current.way+'0';//0是ope数组的下标,表示从current到next的操作是ope[0]

                    if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }

                }
                  // cout<<"111"<<endl;
                //并列的if块体现了广度的意思
                if(current.b<vb)
                {
                    next.a=current.a;
                    next.b=vb;
                    next.way=current.way+'1';

                    if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }
                }


                if(current.a!=0)
                {
                   //  cout<<"222"<<endl;
                    next.a=0;
                    next.b=current.b;
                    next.way=current.way+'2';

                    if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }
                }

                if(current.b!=0){
                    // cout<<"333"<<endl;
                    next.a=current.a;
                    next.b=0;
                    next.way=current.way+'3';

                     if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }
                }

                if(current.a!=0&&current.b!=vb){
                    //a往b中倒水,a倒空且b未溢出
                    // cout<<"444"<<endl;
                    if(current.a<=(vb-current.b)){
                        next.a=0;
                        next.b=current.b+current.a;
                    }
                    //a往b中倒水,b已倒满,a有剩余(a恰倒空已包含在上面的等于中)
                    else if(current.a>(vb-current.b)){
                         next.a=current.a-(vb-current.b);
                         next.b=vb;
                    }
                    next.way=current.way+'4';

                    if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }
                }


                if(current.a!=va&&current.b!=0){
                    //  cout<<"555"<<endl;
                   //b往a中倒水,b倒空且a未溢出
                    if(current.b<=(va-current.a)){
                        next.a=current.a+current.b;
                        next.b=0;
                    }
                    //b往a中倒水,a已倒满,b有剩余(a恰倒空已包含在上面的等于中)
                    else if(current.b>(va-current.a)){
                         next.a=va;
                         next.b=current.b-(va-current.a);
                    }
                    next.way=current.way+'5';
                    if(vis[next.a][next.b]==0)  //说明next这个状态之前没有经历过
                    {
                        que.push(next);
                        vis[next.a][next.b]=1;
                    }
                }
            }

        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/k0_0k/article/details/81200687