zoukankan      html  css  js  c++  java
  • 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 中的水 等于目标水量)

  • 相关阅读:
    MIne FirstBlog
    P6563 [SBCOI2020]一直在你身旁
    P6563 [SBCOI2020]一直在你身旁
    T122085 [SBCOI2020]时光的流逝
    LC 918. Maximum Sum Circular Subarray
    1026 Table Tennis
    LC 1442. Count Triplets That Can Form Two Arrays of Equal XOR
    LC 1316. Distinct Echo Substrings
    LC 493. Reverse Pairs
    1029 Median (二分)
  • 原文地址:https://www.cnblogs.com/LJA001162/p/11218432.html
Copyright © 2011-2022 走看看