1. 程式人生 > >【POJ】3414Pots(單bfs)

【POJ】3414Pots(單bfs)

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 23546   Accepted: 9969   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

題目大意:

給出AB兩個杯子通過三個操作讓兩個杯子其中之一調和出C升的水量,其中有三個操作,

1.把某杯子的水清空

2.把某杯子的水倒滿

3.把某杯子的水倒入另一個杯子中

根據這三個操作(實際操作可 化為6個,畢竟兩杯子不相同)求出得到C升水的最短序列,

最後要求輸出操作的!

 

 思路:這個就是bfs 列舉每一層的所有狀態到一個佇列中,不過這個要求輸出操作順序,中間要每次都儲存,後面用棧方便輸出。

我們用一個結構node來表示到達(i,j)狀態時,它的前一個狀態是node.i和node.j且操作時node.k.其中用pre[i][j]來指示node中的節點。

其中用vis[i][j]和dist[i][j]來標記和記錄最短路徑長,用pre[i][j]=x來指示(i,j)狀態的前驅資訊在nodes[x]節點中。

之後就是列舉狀態,0~5

注意:A杯和B杯的狀態在任何時候都不可能是: A非空且不滿 B非空且不滿.所以我們可以通過A和B的當前狀態推出他們的前驅.所以可以不用nodes記錄前驅也行.

程式碼:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<stack>
using namespace std;
const int maxa=100+5;
const int maxb=100+5;
const int maxn=110000;

int A,B,C;
int vis[maxa][maxb],dist[maxa][maxb],pre[maxa][maxb];

struct Cell
{
    int a,b;
    Cell(int a,int b):a(a),b(b){}
};

int cnt;

struct Node
{
    int a,b,t;
    Node(){};
    Node(int a,int b,int t):a(a),b(b),t(t){}
}node[maxn];

queue<Cell> Q;

Cell bfs()
{
    cnt=0;
    memset(vis,0,sizeof(vis));
    dist[0][0]=0;
    vis[0][0]=1;
    Q.push(Cell(0,0));

    while(!Q.empty())
    {
        Cell cell=Q.front();
        Q.pop();

        int a=cell.a;
        int b=cell.b;
        for(int d=0;d<6;d++)
        {
            int na,nb;
            if(d==0) na=A,nb=b;
            else if(d==1) na=a,nb=B;
            else if(d==2) na=0,nb=b;
            else if(d==3) na=a,nb=0;
            else if(d==4)
            {
                int all=a+b;
                na=all>=B?all-B:0;
                nb=all>=B?B:all;
            }
            else if(d==5)
            {
                int all=a+b;
                na=all>=A?A:all;
                nb=all>=A?all-A:0;
            }
            //選擇條件完畢
            if(vis[na][nb]==0)
            {
                vis[na][nb]=1;
                dist[na][nb]=dist[a][b]+1;
                node[cnt++]=Node(a,b,d);
                pre[na][nb]=cnt-1;
                if(na==C||nb==C)//滿足條件退出
                {
                    return Cell(na,nb);
                }
                Q.push(Cell(na,nb));
            }
        }
    }
    return Cell(-1,-1);
}

int main()
{
    scanf("%d%d%d",&A,&B,&C);
    Cell cell=bfs();
    if(cell.a==-1)printf("impossible\n");
    else
    {
        stack<int> S;
        int a=cell.a,b=cell.b;
        while(a!=0||b!=0)
        {
            int p=pre[a][b];
            S.push(node[p].t);
            a=node[p].a,b=node[p].b;
        }
        printf("%d\n",S.size());
        while(!S.empty())
        {
            int x=S.top();S.pop();
            if(x==0||x==1) printf("FILL(%d)\n",x+1);
            else if(x==2||x==3) printf("DROP(%d)\n",x-1);
            else if(x==4) printf("POUR(1,2)\n");
            else if(x==5)printf("POUR(2,1)\n");
        }
    }
    return 0;
}