• 暑假集训每日一题0716(BFS)


    Description

     有三个无刻度标志的水杯,分别可装 a ,b , c升水,并且a>b , a>c , a,b,c,均为正整数。任意两个水杯之间可以相互倒水。用

    杯子x给y倒水的时必须一直持续到把杯子y倒满或者把杯子x倒空,而不能中途停止。倒水过程中水量不变。最初的时候只有大杯子
    装满水,其他两个杯子为空。问能不能量出x升水,如果可以,最少需要多少步?

    Input

     输入有多组数据。每组数据为一行,有4个正整数a,b,c,x且满足:a>b,a>c,a>x,a,b,c,x <= 1000。

    Output

     输出一个整数。如果可以量出x升水,输出需要的最少步骤,否则,输出-1。

    Sample Input

    6 3 1 4
    7 3 2 5

    Sample Output

    3
    1
     
    将每个杯子中的水量组合成状态,进行宽搜即可。
     
    View Code
    #include <stdio.h>
    #include <queue>
    #define N 1001
    #define MIN(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    typedef struct node
    {
        int a[3];
    }node;
    int v[3],x;
    int t[N][N];
    bool isok(node tmp)
    {
        for(int i=0;i<3;i++)    if(tmp.a[i]==x) return true;
        return false;
    }
    node tran(node tmp,int i,int j)
    {
        int d=MIN(tmp.a[i],v[j]-tmp.a[j]);
        tmp.a[i]-=d;
        tmp.a[j]+=d;
        return tmp;
    }
    void bfs()
    {
        queue<node> q;
        node cur,next;
        bool success=false;
        int i,j,ans;
        for(i=0;i<=v[0];i++)
        {
            for(j=0;j<=v[0];j++)    t[i][j]=-1;
        }
        cur.a[0]=v[0];
        cur.a[1]=0;
        cur.a[2]=0;
        t[v[0]][0]=0;
        q.push(cur);
        while(!q.empty() && !success)
        {
            cur=q.front(),q.pop();
            if(isok(cur))
            {
                success=true;
                ans=t[cur.a[0]][cur.a[1]];
            }
            for(i=0;i<3 && !success;i++)
            {
                for(j=0;j<3 && !success;j++)
                {
                    if(i==j)    continue;
                    if(cur.a[i]==0 || cur.a[j]==v[j])   continue;
                    next=tran(cur,i,j);
                    if(t[next.a[0]][next.a[1]]!=-1) continue;
                    t[next.a[0]][next.a[1]]=t[cur.a[0]][cur.a[1]]+1;
                    if(isok(next))
                    {
                        success=true;
                        ans=t[next.a[0]][next.a[1]];
                    }
                    else    q.push(next);
                }
            }
        }
        if(success) printf("%d\n",ans);
        else    puts("-1");
    }
    int main()
    {
        while(~scanf("%d%d%d%d",&v[0],&v[1],&v[2],&x))   bfs();
        return 0;
    }
  • 相关阅读:
    C#的多态性
    冒泡法,改进冒泡法排序和反序算法
    [收藏]D3D渲染流程简介
    [收藏]字符串表达式求值
    Windows下使用VC++编译GNU科学计算库 GNU Scientific Library(GSL)
    VC++ 高精度定时timeSetEvent和回调成员方法
    [收藏]C/C++数组名与指针区别深层探索
    线性表操作
    线性表综合运用
    两个线性表融合的算法
  • 原文地址:https://www.cnblogs.com/algorithms/p/2597753.html
Copyright © 2020-2023  润新知