zoukankan      html  css  js  c++  java
  • POJ 3414 Pots(广搜输出路径)

    Description:

    You are given two pots, having the volume of A and B liters respectively. The following operations can be performed:

    1. FILL(i)        fill the pot i (1 ≤ ≤ 2) from the tap;
    2. DROP(i)      empty the pot i to the drain;
    3. POUR(i,j)    pour from pot i to pot j; after this operation either the pot j is full (and there may be some water left in the pot i), or the pot i is empty (and all its contents have been moved to the pot j).

    Write a program to find the shortest possible sequence of these operations that will yield exactly C liters of water in one of the pots.

    Input:

    On the first and only line are the numbers AB, and C. These are all integers in the range from 1 to 100 and C≤max(A,B).

    Output:

    The first line of the output must contain the length of the sequence of operations K. The following K lines must each describe one operation. If there are several sequences of minimal length, output any one of them. If the desired result can’t be achieved, the first and only line of the file must contain the word ‘impossible’.

    Sample Input:

    3 5 4

    Sample Output:

    6
    FILL(2)
    POUR(2,1)
    DROP(1)
    POUR(2,1)
    FILL(2)
    POUR(2,1)

    题意:有两个容器,容量分别为a和b,你可以进行三种操作,观察能否让其中一个容器的水的容量为c,输出最少操作步数及其路径,最少步数当然一个BFS就可以了,这里和 HDU 1495 非常可乐有点类似,难点在于如何输出路径,其实分析之后发现路径是可以通过递归实现的。虽说有三种操作,但是实际操作起来却又分为六种情况了,剩下就是BFS和一个DFS递归输出了。
    #include<stdio.h>
    #include<queue>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int N=110;
    
    struct node
    {
        int a, b, k;
    };
    struct Node
    {
        int prea, preb, op;
    }no[N][N]; ///结构体定义二维数组。。。是第一次尝试,这个二维数组记录上一个操作以及这次操作的操作序号(0~5),这个结构体是为了便于输出建立的
    int a, b, c, vis[N][N]; ///vis数组为标记数组
    char s[20][20] = { "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)" }; ///这些就是我们想要的六种操作了
    
    void DFS(int x, int y) ///DFS递归输出
    {
        if (x == 0 && y == 0)
            return ; ///当都为0时说明已经递归到最初的地方了
    
        DFS(no[x][y].prea, no[x][y].preb);
    
        printf("%s
    ", s[no[x][y].op]);
    }
    
    void BFS()
    {
        int i;
        queue<node>Q;
        node now, next;
    
        now.a = now.b = now.k = 0;
    
        Q.push(now);
        vis[now.a][now.b] = 1;
    
        while (!Q.empty())
        {
            now = Q.front(); Q.pop();
    
            for (i = 0; i < 6; i++) ///六种操作,i和上面的s字符串的下标都是一一对应的
            {
                next = now;
    
                if (now.a == c || now.b == c) ///达到要求时开始输出
                {
                    printf("%d
    ", now.k); ///先输出步数
    
                    DFS(now.a, now.b);
    
                    return ;
                }
    
                if (i == 0) next.a = a;
                else if (i == 1) next.b = b;
                else if (i == 2) next.a = 0;
                else if (i == 3) next.b = 0;
                else if (i == 4) ///当需要从一个容器倒入另一个容器时,就要开始判断两个容器量的多少,因为是不能溢出的
                {
                    if (now.a >= b-now.b)
                    {
                        next.b = b;
                        next.a = now.a - (b-now.b);
                    }
                    else
                    {
                        next.a = 0;
                        next.b = now.b + now.a;
                    }
                }
                else if (i == 5)
                {
                    if (now.b >= a-now.a)
                    {
                        next.a = a;
                        next.b = now.b - (a-now.a);
                    }
                    else
                    {
                        next.b = 0;
                        next.a = now.b + now.a;
                    }
                }
                if (!vis[next.a][next.b]) ///最后在进队列时记录下上一次的状态以及这一次的操作序号,便于递归输出
                {
                    vis[next.a][next.b] = 1;
                    next.k = now.k + 1;
                    no[next.a][next.b].prea = now.a;
                    no[next.a][next.b].preb = now.b;
                    no[next.a][next.b].op = i;
    
                    Q.push(next);
                }
            }
        }
    
        printf("impossible
    "); ///没有找到满足情况的可能时就输出impossible
    }
    
    int main ()
    {
        while (scanf("%d%d%d", &a, &b, &c) != EOF)
        {
            memset(vis, 0, sizeof(vis));
    
            BFS();
        }
    
        return 0;
    }
  • 相关阅读:
    php 三元运算符简洁用法
    Linux 获取网卡信息
    《构建之法》读后感
    毫秒数据字符串转换为DateTime
    POST请求——HttpWebRequest
    多个不同类对象传输思路
    WCF 大文件传输配置
    WCF配置文件详解
    C# 元组、匿名对象、ref&out
    C#控制台关闭之前做一些操作
  • 原文地址:https://www.cnblogs.com/syhandll/p/4834481.html
Copyright © 2011-2022 走看看