• c++ 宽搜(倒水)


    题目描述

    有一个很大的水缸和二个容量分别为X和Y的水壶,按照以下的规则倒水,问最少经几次倒水后,可得到Z升水
    规则1:水缸向水壶1倒水,将水壶1装满;
    规则2:水缸向水壶2倒水,将水壶2装满;
    规则3:水壶1向水缸倒水,直到水壶1空;
    规则4:水壶2向水缸倒水,直到水壶2空;
    规则5:水壶1向水壶2倒水,直到水壶1空了或者水壶2满了;
    规则6:水壶2向水壶1倒水,直到水壶2空了或者水壶1满了;

    输入

    只有一行数据,包括以空格分隔的三个数字,分别表示水壶1( <= 100)、 水壶2的水量( <= 100 )以及期望得到的水量( <=100 )。

    输出

    若经若干次倒水能得到所要求的水量,则输出最少的倒水次数;若无论如何倒水都无法得到规定的水量,则输出No Solution!

    样例输入

    4 3 1
    

    样例输出

    2
    

    AC代码

    #include <iostream>
    #include <string.h>
    using namespace std;
    struct point //结构体
    {
        int x, y, step;
    };
    bool used[101][101];
    point q[20000], s;
    int xx, yy, t;
    int f = 1, e = 1;
    point gen(point u, int cc)//尝试枚举每一个规则
    {
         point v = u;
         v.step = u.step + 1;
         //开始枚举规则
         if (cc == 1) v.x = xx;//水缸向水壶1倒水,将水壶1装满
         else if (cc == 2) v.y = yy;//水缸向水壶2倒水,将水壶2装满
         else if (cc == 3) v.x = 0;//水壶1向水缸倒水,直到水壶1空
         else if (cc == 4) v.y = 0;//水壶2向水缸倒水,直到水壶2空
         else if (cc == 5)//水壶1向水壶2倒水,直到水壶1空了或者水壶2满了
         {
             if (u.x + u.y <= yy) v.x = 0, v.y = u.x + u.y;//如果y能把x和y的水量都装下
             else v.y = yy, v.x = u.x + u.y - yy;//y装不下从x倒过来的水
         }
         else//水壶2向水壶1倒水,直到水壶2空了或者水壶1满了
         {
             if (u.x + u.y <= xx) v.y = 0, v.x = u.x + u.y;//如果x能把x和y的水量都装下
             else v.x = xx, v.y = u.x + u.y - xx;//x装不下从y倒过来的水
         }
         return v;
    }
    int main()
    {
         scanf ("%d %d %d", &xx, &yy, &t);//xx是x桶的水量,yy是y桶的水量
         if (t == 0)
         {
             printf ("0
    ");
             return 0;
         }
         memset (used, 0, sizeof (used));//memset
         s.x = 0, s.y = 0, s.step = 0;
         q[1] = s;
    ///////////开始宽搜///////////////
         while (f <= e)//f是出队下标  e是入队下标
         {
             point u = q[f++];//选定的元素
             for (int i = 1; i <= 6; i++)//尝试枚举6个规则
             {
                 point v = gen(u, i);//v就是将要入队的元素
                 if (used[v.x][v.y] == 0)
                 {
                     if (v.x == t || v.y == t)//任意一个杯子里面有目标水量
                     {
                         printf ("%d
    ", v.step);//就打印步数
                         return 0;//默默退出
                     }
                     q[++e] = v;//入队
                     used[v.x][v.y] = 1;//表示已经被选择过
                 }
             }
         }
         printf ("No Solution!
    ");//如果无法完成
         return 0;
    }
    
    

    思路分析

    step1:将初始状态入队
    step2:以初始状态为中心按6个规则向6个方向寻找可能的值入队
    step3:在通过可能的值向6个方向继续拓展,直到找到目标(水壶1 或 水壶2 中的水 等于目标水量)

  • 相关阅读:
    自动发现
    1.1 开启二进制日志
    mysql
    html常见的块元素和行内元素(特别注意个别块元素不能嵌套其他块元素)
    Linux查看物理CPU个数、核数、逻辑CPU个数
    查看linux服务器的系统信息
    谷歌浏览器无法输入中文——解决
    Linux下查看正在使用的端口
    入园第三天-记录
    Visual Studio2015 Community一些必备插件
  • 原文地址:https://www.cnblogs.com/LJA001162/p/11218432.html
Copyright © 2020-2023  润新知