当前位置: 首页 > news >正文

《算法笔记》8.2小节——搜索专题->广度优先搜索(BFS)问题 A: Jugs

题目描述

In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with the following puzzle. They were given a 3-gallon jug and a 5-gallon jug and were asked to fill the 5-gallon jug with exactly 4 gallons. This problem generalizes that puzzle.

    You have two jugs, A and B, and an infinite supply of water. There are three types of actions that you can use: (1) you can fill a jug, (2) you can empty a jug, and (3) you can pour from one jug to the other. Pouring from one jug to the other stops when the first jug is empty or the second jug is full, whichever comes first. For example, if A has 5 gallons and B has 6 gallons and a capacity of 8, then pouring from A to B leaves B full and 3 gallons in A.

    A problem is given by a triple (Ca,Cb,N), where Ca and Cb are the capacities of the jugs A and B, respectively, and N is the goal. A solution is a sequence of steps that leaves exactly N gallons in jug B. The possible steps are

    fill A 
    fill B 
    empty A 
    empty B 
    pour A B 
    pour B A 
    success

    where "pour A B" means "pour the contents of jug A into jug B", and "success" means that the goal has been accomplished.

    You may assume that the input you are given does have a solution.

输入

Input to your program consists of a series of input lines each defining one puzzle. Input for each puzzle is a single line of three positive integers: Ca, Cb, and N. Ca and Cb are the capacities of jugs A and B, and N is the goal. You can assume 0 < Ca <= Cb and N <= Cb <=1000 and that A and B are relatively prime to one another. 

输出

Output from your program will consist of a series of instructions from the list of the potential output lines which will result in either of the jugs containing exactly N gallons of water. The last line of output for each puzzle should be the line "success". Output lines start in column 1 and there should be no empty lines nor any trailing spaces.

样例输入
3 7 1
9 32 6
样例输出
fill B
pour B A
empty A
pour B A
success
fill B
pour B A
empty A
pour B A
empty A
pour B A
empty A
pour B A
fill B
pour B A
empty A
pour B A
empty A
pour B A
empty A
pour B A
empty A
pour B A
fill B
pour B A
empty A
pour B A
empty A
pour B A
success

分析:原题应该是这个:UVA - 571 ,但是原题可以过的代码在Codeup上就是过不了。可能是因为codeup上只有检查到容器B的水为n,才符合要求。

首先应该可以看出来,两个壶的条件下,倒水的过程实际上就是求最大公约数的更相减损术。只要目标值是两个壶容量的最大公约数的倍数,就一定有解。如果不考虑步骤,只要一个壶一直往另一个壶倒水,总能够达到要求。

#include<algorithm>
#include <iostream>
#include  <cstdlib>
#include  <cstring>
#include   <string>
#include   <vector>
#include   <cstdio>
#include    <queue>
#include    <stack>
#include    <ctime>
#include    <cmath>
#include      <map>
#include      <set>
#define INF 0x3f3f3f3f
#define db1(x) cout<<#x<<"="<<(x)<<endl
#define db2(x,y) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<endl
#define db3(x,y,z) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<endl
#define db4(x,y,z,a) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#a<<"="<<(a)<<endl
#define db5(x,y,z,a,r) cout<<#x<<"="<<(x)<<", "<<#y<<"="<<(y)<<", "<<#z<<"="<<(z)<<", "<<#a<<"="<<(a)<<", "<<#r<<"="<<(r)<<endl
using namespace std;

typedef struct node
{
    int cnt_a,cnt_b,fat,op;
}node;

void print(node a)
{
//    db4(a.cnt_a,a.cnt_b,a.fat,a.op);
    if(a.op==1)printf("fill A\n");
    else if(a.op==2)printf("fill B\n");
    else if(a.op==3)printf("empty A\n");
    else if(a.op==4)printf("empty B\n");
    else if(a.op==5)printf("pour A B\n");
    else if(a.op==6)printf("pour B A\n");
    return;
}

int main(void)
{
    #ifdef test
    freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    clock_t start=clock();
    #endif //test

    int ca,cb,n;
    while(~scanf("%d%d%d",&ca,&cb,&n))
    {
        if(n==0)
        {
            printf("success\n");continue;
        }
        int flag[ca+5][cb+5],l=0,r=1;
        for(int i=0;i<=ca;++i)
            for(int j=0;j<=cb;++j)
                flag[i][j]=0;

        vector<node>sta;
        node temp;
        temp.cnt_a=temp.cnt_b=0,temp.fat=-1,temp.op=0;
        sta.push_back(temp);
        flag[0][0]=1;

        while(l<r)
        {
            int ll=l,rr=r,f=0,index=-1;
            for(int i=ll;i<rr;++i)
            {
//                db3(sta[i].cnt_a,sta[i].cnt_b,i);
//                if(flag[sta[i].cnt_a][sta[i].cnt_b]==1)continue;
//                else flag[sta[i].cnt_a][sta[i].cnt_b]=1;

                if(sta[i].cnt_b==n)
                {
                    f=1;index=i;break;
                }

                if(sta[i].cnt_a<ca)//fill A
                {
                    temp.cnt_a=ca;temp.cnt_b=sta[i].cnt_b;temp.fat=i,temp.op=1;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
                if(sta[i].cnt_b<cb)//fill B
                {
                    temp.cnt_b=cb;temp.cnt_a=sta[i].cnt_a;temp.fat=i,temp.op=2;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
                if(sta[i].cnt_a>0)//empty A
                {
                    temp.cnt_a=0;temp.cnt_b=sta[i].cnt_b;temp.fat=i,temp.op=3;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
                if(sta[i].cnt_b>0)//empty B
                {
                    temp.cnt_b=0;temp.cnt_a=sta[i].cnt_a;temp.fat=i,temp.op=4;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
                if(sta[i].cnt_b<cb&&sta[i].cnt_a>0)//pour A B
                {
                    if(cb-sta[i].cnt_b>=sta[i].cnt_a)temp.cnt_b=sta[i].cnt_b+sta[i].cnt_a,temp.cnt_a=0;
                    else temp.cnt_a=sta[i].cnt_a-cb+sta[i].cnt_b,temp.cnt_b=cb;
                    temp.fat=i,temp.op=5;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
                if(sta[i].cnt_b>0&&sta[i].cnt_a<ca)//pour B A
                {
                    if(ca-sta[i].cnt_a>=sta[i].cnt_b)temp.cnt_a=sta[i].cnt_a+sta[i].cnt_b,temp.cnt_b=0;
                    else temp.cnt_b=sta[i].cnt_b-ca+sta[i].cnt_a,temp.cnt_a=ca;
                    temp.fat=i,temp.op=6;
                    if(!flag[temp.cnt_a][temp.cnt_b])flag[temp.cnt_a][temp.cnt_b]=1,sta.push_back(temp),r++;
                }
            }
            l=rr;
//            db4(l,r,f,index);
            if(f==1)
            {
                stack<node>ans;
                while(index!=-1)
                {
//                    db1(index);
                    ans.push(sta[index]);index=sta[index].fat;
                }

                while(!ans.empty())
                {
                    node cnt=ans.top();ans.pop();
                    print(cnt);
                }
                printf("success\n");
                break;
            }
        }
//        db3(ca,cb,n);
    }

    #ifdef test
    clockid_t end=clock();
    double endtime=(double)(end-start)/CLOCKS_PER_SEC;
    printf("\n\n\n\n\n");
    cout<<"Total time:"<<endtime<<"s"<<endl;        //s为单位
    cout<<"Total time:"<<endtime*1000<<"ms"<<endl;    //ms为单位
    #endif //test
    return 0;
}

相关文章:

  • 人工智能与人的智能,思维模型分享【3】直觉
  • 西方力推的5G O-RAN难以撼动传统通信设备商
  • c语言经典基础编程题
  • 【数据结构】6栈
  • Linux--gdb/cgdb
  • 【Go】Go MongoDB 快速入门
  • 使用 pytesseract 进行 OCR 识别:以固定区域经纬度提取为例
  • 过滤器(Filter)与拦截器(Interceptor)
  • Flutter 学习之旅 之 flutter 使用 shared_preferences 实现简单的数据本地化保存封装
  • MySQL 深度分页如何优化?
  • 【Unity6打包Android】游戏启动的隐私政策弹窗(报错处理)
  • 从硬件定时器原理学会多任务调度
  • 筛选法找质数(信息学奥赛一本通-2040)
  • 陶陶摘苹果(信息学奥赛一本通-1103)
  • 46. HarmonyOS NEXT 登录模块开发教程(一):模态窗口登录概述
  • 操作系统高频面试题
  • 机器学习模型-从线性回归到神经网络
  • LuaJIT 学习(2)—— 使用 FFI 库的几个例子
  • 密码学研究热点
  • 城市客运安全员适合哪几类人报考
  • 住建部:截至去年底常住人口城镇化率达到67%
  • 新华社原香港分社副社长、深圳市委原副书记秦文俊逝世
  • 上海发文加强直播经济技能人才培养:三年新培养持证直播技能人才5万名
  • 前四月国家铁路发送货物12.99亿吨,同比增长3.6%
  • 减负举措如何助力基层干部轻装上阵?记者一线调查
  • 聘期三年已至:37岁香港青年叶家麟卸任三亚市旅游发展局局长