三个水杯问题

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


很有意思的问题,第一次看觉得好像汉罗塔,其实是在搜索树,每个树的节点至多有6个叶子,代表6种倒水情况,因为最大的体积为整数100,因此复杂度不超过100*100*100,因为vis[100][100][100]不会让节点重复入队,树的节点总数不超过100万,因此BFS可行,网上虽然也有不少题解,不过都没看见复杂度分析,吐槽一下,不分析复杂度就直接搜索的都是耍流氓。


//my AC code


#include <iostream>
#include <queue>
#include <cstring>
using namespace std;

struct Node
{
    int v1,v2,v3,step;
    Node() { step=-1; }
    Node(int x,int y,int z,int w):v1(x),v2(y),v3(z),step(w) {}
};
int vis[100][100][100];
Node start,dest;
int vm1,vm2,vm3;
queue<Node> q;

void bfs()
{
    while(!q.empty())
        q.pop();
    q.push(start);
    vis[start.v1][start.v2][start.v3]=1;
    while(!q.empty())
    {
        Node t=q.front();
        q.pop();
        //cout<<t.v1<<" "<<t.v2<<" "<<t.v3<<" "<<t.step<<endl;
        if(t.v1==dest.v1 && t.v2==dest.v2 && t.v3==dest.v3)
        {
            dest.step=t.step;
            return;
        }
        int v1=t.v1;
        int v2=t.v2;
        int v3=t.v3;
        int step=t.step;
        if(v1>0) //v1中有水
        {
            if(v1>vm2-v2) //v1中的水比v2中剩下的空间大
            {
                if(!vis[v1-(vm2-v2)][vm2][v3])
                {
                    q.push(Node(v1-(vm2-v2),vm2,v3,step+1));
                    vis[v1-(vm2-v2)][vm2][v3]=1;
                }
            }
            else
            {
                if(!vis[0][v1+v2][v3])
                {
                    q.push(Node(0,v1+v2,v3,step+1));
                    vis[0][v1+v2][v3]=1;
                }
            }
            if(v1>vm3-v3) //v1中的水比v3中剩下的空间大
            {
                if(!vis[v1-(vm3-v3)][v2][vm3])
                {
                    q.push(Node(v1-(vm3-v3),v2,vm3,step+1));
                    vis[v1-(vm3-v3)][v2][vm3]=1;
                }
            }
            else
            {
                if(!vis[0][v2][v1+v3])
                {
                    q.push(Node(0,v2,v1+v3,step+1));
                    vis[0][v2][v1+v3]=1;
                }
            }
        }
        if(v2>0) //v2中有水
        {
            if(v2>vm1-v1) //v2中的水比v1总剩下空间大
            {
                if(!vis[vm1][v2-(vm1-v1)][v3])
                {
                    q.push(Node(vm1,v2-(vm1-v1),v3,step+1));
                    vis[vm1][v2-(vm1-v1)][v3]=1;
                }
            }
            else
            {
                if(!vis[v1+v2][0][v3])
                {
                    q.push(Node(v1+v2,0,v3,step+1));
                    vis[v1+v2][0][v3]=1;
                }
            }
            if(v2>vm3-v3)
            {
                if(!vis[v1][v2-(vm3-v3)][vm3])
                {
                    q.push(Node(v1,v2-(vm3-v3),vm3,step+1));
                    vis[v1][v2-(vm3-v3)][vm3]=1;
                }
            }
            else
            {
                if(!vis[v1][0][v2+v3])
                {
                    q.push(Node(v1,0,v2+v3,step+1));
                    vis[v1][0][v2+v3]=1;
                }
            }
        }
        if(v3>0)
        {
            if(v3>vm1-v1)
            {
                if(!vis[vm1][v2][v3-(vm1-v1)])
                {
                    q.push(Node(vm1,v2,v3-(vm1-v1),step+1));
                    vis[vm1][v2][v3-(vm1-v1)]=1;
                }
            }
            else
            {
                if(!vis[v1+v3][v2][0])
                {
                    q.push( Node(v1+v3,v2,0,step+1) );
                    vis[v1+v3][v2][0]=1;
                }
            }
            if(v3>vm2-v2)
            {
                if(!vis[v1][vm2][v3-(vm2-v2)])
                {
                    q.push(Node(v1,vm2,v3-(vm2-v2),step+1));
                    vis[v1][vm2][v3-(vm2-v2)]=1;
                }
            }
            else
            {
                if(!vis[v1][v2+v3][0])
                {
                    q.push(Node(v1,v2+v3,0,step+1));
                    vis[v1][v2+v3][0]=1;
                }
            }
        }
    }
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        memset(vis,0,sizeof(vis));
        cin>>vm1>>vm2>>vm3;
        start.v1=vm1;
        start.v2=0;
        start.v3=0;
        start.step=0;
        cin>>dest.v1>>dest.v2>>dest.v3;
        if(vm1!=dest.v1+dest.v2+dest.v3)
        {
            cout<<"-1"<<endl; continue;
        }
        dest.step=-1;
        bfs();
        cout<<dest.step<<endl;
    }
    return 0;
}


你可能感兴趣的:(三个水杯问题)