Pots POJ - 3414 (搜索+记录路径)


Pots

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 22688   Accepted: 9626   Special Judge

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)

Source

Northeastern Europe 2002, Western Subregion

题意:

有二个水壶,对水壶有三种操作:

1)FILL(i),将i水壶的水填满;

2)DROP(i),将水壶i中的水全部倒掉;

3)POUR(i,j)将水壶i中的水倒到水壶j中,若水壶 j 满了,则 i 剩下的就不倒了,问进行多少步操作,并且怎么操作,输出操作的步骤,两个水壶中的水可以达到C这个水量。如果不可能则输出impossible。初始时两个水壶是空的,没有水。

思路:

模拟一下,然后如果当前的状态已经出现过了就说明不可以这样子,必须要用其他操作,这个和poj3087的题目有点像,这里还需要储存一个路径,这个和poj3984有点像,poj3984之前的博客里面用了递归的方式输出路径,这一回用了栈,两种方法应该都可以做的,具体的看代码吧,注释已经很清楚了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-10
#define PI acos(-1.0)
#define _e exp(1.0)
#define ll long long
const int maxn=110;
struct cup
{
    int x,y;            //a和b的当前水的状态
    int step;
    int flag;           //标记操作,是操作几
    cup *pre;           //记录路径的玩意儿
};
queue<cup>que;
stack<int>R;
int a,b,e;
int vis[maxn][maxn]={0};     //记录当前的状态是否到达过
int ans;

void bfs(int x,int y)
{
    cup c;
    cup t[317];           //目前瓶子里剩余的水量
    c.x=0;
    c.y=0;
    c.flag=0;
    c.pre=NULL;
    c.step=0;
    que.push(c);
    vis[x][y]=1;
    int count=-1;
    while(!que.empty())
    {
        count++;
        t[count]=que.front();
        que.pop();
        for(int i=1;i<=6;i++)
        {
            switch(i)
            {
                case 1:             //fill a
                    c.x=a;
                    c.y=t[count].y;
                    c.flag=1;
                    break;
                case 2:             //fill b
                    c.x=t[count].x;
                    c.y=b;
                    c.flag=2;
                    break;
                case 3:             //drop a
                    c.x=0;
                    c.y=t[count].y;
                    c.flag=3;
                    break;
                case 4:             //drop b
                    c.x=t[count].x;
                    c.y=0;
                    c.flag=4;
                    break;
                case 5:             //pour a to b
                    if(t[count].x>b-t[count].y)     //a可以装满b
                    {
                        c.x=t[count].x-(b-t[count].y);
                        c.y=b;
                    }
                    else                            //a不能装满b
                    {
                        c.x=0;
                        c.y=t[count].y+t[count].x;
                    }
                    c.flag=5;
                    break;
                case 6:           //pour b to a
                    if(t[count].y>a-t[count].x)     //b可以装满a
                    {
                        c.y=t[count].y-(a-t[count].x);
                        c.x=a;
                    }
                    else                            //b不可以装满a
                    {
                        c.x=t[count].x+t[count].y;
                        c.y=0;
                    }
                    c.flag=6;
                    break;
            }
            if(vis[c.x][c.y])
                continue;
            vis[c.x][c.y]=1;
            c.step=t[count].step+1;
            c.pre=&t[count];
            if(c.x==e || c.y==e)
            {
                ans=c.step;
                while(c.pre)
                {
                    R.push(c.flag);
                    c=*c.pre;
                }
                return;
            }
            que.push(c);
        }
    }
}
void print()
{
    while(!R.empty())
    {
        int i=R.top();
        R.pop();
        switch(i)
        {
            case 1:cout<<"FILL(1)"<<endl;break;
            case 2:cout<<"FILL(2)"<<endl;break;
            case 3:cout<<"DROP(1)"<<endl;break;
            case 4:cout<<"DROP(2)"<<endl;break;
            case 5:cout<<"POUR(1,2)"<<endl;break;
            case 6:cout<<"POUR(2,1)"<<endl;break;
        }
    }
}
int main()
{
    cin>>a>>b>>e;
    bfs(0,0);
    if(ans==0)
        cout<<"impossible"<<endl;
    else
    {
        cout<<ans<<endl;
        print();
    }
    return 0;
}

原文地址:https://www.cnblogs.com/smallhester/p/9607966.html

时间: 2024-10-10 15:10:42

Pots POJ - 3414 (搜索+记录路径)的相关文章

hdu 1664(数论+同余搜索+记录路径)

Different Digits Time Limit: 10000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1430    Accepted Submission(s): 392 Problem Description Given a positive integer n, your task is to find a positive integer m, w

POJ 3414 Pot (输出路径)【BFS】

<题目链接> 题目大意: 有两个容量的空杯子,能够对这两个空杯子进行三种操作: 分别是fill(a),装满a杯子: drop(a),倒空a杯子: pour(a,b),将a杯子中的水倒入b杯子中: 现在问你,是否能够通过这三种操作,使得这两个杯子中至少有一个杯子中含有c体积的水,如果不行,输出"impossible",如果可以,输出操作的步数,以及每一步的具体操作. 解题分析: 此题与一道输出路径的很相像,只不过那道题是输出每一次操作对应的点的状态,而此题是要输出具体的操作.

poj 1787 背包+记录路径

http://poj.org/problem?id=1787 Charlie's Change Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4512   Accepted: 1425 Description Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffee at co

Pots POJ - 3414【状态转移bfs+回溯】

典型的倒水问题: 即把两个水杯的每种状态视为bfs图中的点,如果两种状态可以转化,即可认为二者之间可以连一条边. 有3种倒水的方法,对应2个杯子,共有6种可能的状态转移方式.即相当于图中想走的方法有6种,依次枚举即可. 用一个二维数组标记状态,以免重复. 难点在于输出路径,即bfs回溯. 我的处理方法是,在bfs的队列基础上,用一个vector保存每一个可能的状态,即每个状态对应一个编号.同时结构体中不仅保存每个状态的信息,而且还要保存每个状态的对应编号和上一个状态的对应编号. 那么,当bfs到

(简单) POJ 3414 Pots,BFS+记录路径。

Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap; DROP(i)      empty the pot i to the drain; POUR(i,j)    pour from

POJ 3414 Pots 记录路径的广搜

Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)        fill the pot i (1 ≤ i ≤ 2) from the tap; DROP(i)      empty the pot i to the drain; POUR(i,j)    pour from

广搜+输出路径 POJ 3414 Pots

POJ 3414 Pots Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13547   Accepted: 5718   Special Judge Description You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i)

POJ 3414 Pots(罐子)

p.MsoNormal { margin-bottom: 10.0000pt; font-family: Tahoma; font-size: 11.0000pt } h1 { margin-top: 5.0000pt; margin-bottom: 5.0000pt; text-align: left; font-family: 宋体; font-weight: bold; font-size: 24.0000pt } span.10 { font-family: "Times New Rom

poj 1166 The Clocks 记录路径的广搜

题意: 给9个时钟的初始状态,和一些对某几个钟的操作,求最少经过几步能到目标状态(全指向12点). 分析: 明显的广搜,但实现起来的细节要注意:1.因为要记录路径,所以要在整个程序执行过程中扩展出的节点在输出路径前不能销毁, 故采用静态内存分配的方法(开node[600000],用get_node()创建节点.2.queue<node>比queue<int>要多花1别的时间. //poj 1166 //sep9 #include <iostream> #include