afterward

导航

 
View Code
/* pku 3414 Pots BFS+记录路径2011-04-15 18:00题目意思.
1. 给出两个容积分别为 A 、B 的空瓶子,求经过下列操作是否能得到某个瓶子 装 体积为 C 的水。
2.  1> 把某个瓶子装满,2> 把某个瓶子的水倒光,3> 把某个瓶子的水倒入另一个。

思路: 由于 某个状态最多可以推出 六个状态。

            1>  当 A 瓶未满时,把 A 瓶装满          2> 当 B 瓶未满时,把 B 瓶装满

            3>  当 A 瓶非空时,把 A 瓶倒光         4> 当 B 瓶非空时,把 B 瓶倒光

            5> 当 A 瓶非空且 B 瓶未满时.从 A 倒入 B     6> 当 B 瓶非空且 A 瓶未满时,从 B 倒入 A

     路径保存,这里用二维数组保存,其实用一维都行。然后个递归函数据输出了

代码:

  3 5 4

 */

#include <cstdlib>
#include <iostream>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=109;
int A,B,C;
/*
 *
 */
struct node
{
    int a,b;              //当前状态,各个容器装的水
    int prea,preb;  //上一状态
    int tag;             //经过什么操作得到当前状态:1--6
    int step;          //当前是第几步
}path[maxn][maxn];
bool used[maxn][maxn];

queue<node> que;
void output(int a,int b)               //通过递归调用来输出结果
{
    if(path[a][b].a==0&&path[a][b].b==0)
        return ;
    output(path[a][b].prea,path[a][b].preb);
    switch(path[a][b].tag)
    {
        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;
    }
}
void push(node v)             //单独写个小函数,加入某个节点
{
    if(!used[v.a][v.b])
    {
        que.push(v);//cout<<" "<<v.a<<" "<<v.b<<endl;
        path[v.a][v.b]=v;
        used[v.a][v.b]=true;
    }
}
void bfs()
{
    path[0][0].prea=path[0][0].preb=-1;
    path[0][0].a=path[0][0].b=0;
    path[0][0].step=0;
    memset(used,false,sizeof(used));
    used[0][0]=true;
    while(!que.empty())
        que.pop();
    que.push(path[0][0]);
    while(!que.empty())
    {
        node u=que.front();
        que.pop();cout<<"pop-------:"<<u.a<<" "<<u.b<<endl;
        if(u.a==C || u.b==C)
        {
            cout<<u.step<<endl;
            output(u.a,u.b);
            return ;
        }

        node v=u;
        v.prea=u.a;
        v.preb=u.b;
        v.step++;  cout<<v.step<<endl;
        if(u.a!=A)              // 1. 把 a 加满
        {
            v.a=A; v.b=u.b;                 //这里注意:if 一般都是判断上一节点 u ,而且可能改变的两个值都写一下
            v.tag=1;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;

        }
        if(u.b!=B)              // 2. 把 b 加满
        {
            v.a=u.a; v.b=B;
            v.tag=2;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;
        }
        if(u.a!=0)              // 3. 把 a 倒光
        {
            v.a=0; v.b=u.b;
            v.tag=3;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;

        }
        if(u.b!=0)              //4. 把 b 倒光
        {
            v.a=u.a; v.b=0;
            v.tag=4;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;

        }
        int sum=u.a+u.b;
        if(u.a!=0&&u.b!=B)      // 5. 从 a 倒给 b
        {
            if(sum>=B)
                v.b=B, v.a=sum-B;
            else
                v.a=0, v.b=sum;
            v.tag=5;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;
        }
        if(u.a!=A&&u.b!=0)      // 6. 从 b 到给 a
        {
            if(sum>=A)
                v.a=A, v.b=sum-A;
            else
                v.a=sum, v.b=0;
            v.tag=6;
            push(v);cout<<"push:"<<v.a<<" "<<v.b<<endl;
        }
    }
    cout<<"impossible"<<endl;
}

int main(int argc, char** argv)
{
    while(cin>>A>>B>>C)
    {
        bfs();
    }
    return 0;
}

倒水问题

注释掉一些输出就可以了。这个代码不错,保留!

ACM pku 3414 Pots 关于bfs的一个好题
Pots
Time Limit: 1000MS  Memory Limit: 65536K
Total Submissions: 6902  Accepted: 2890  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)        fill the pot i (1 ≤ i ≤ 2) from the tap;
DROP(i)      empty the pot i to the drain;
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 A, B, 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)

posted on 2012-08-03 10:39  afterward  阅读(159)  评论(0编辑  收藏  举报