POJ-3414-Pots(BFS)

Pots

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)

題意:
分別給你兩個杯子的容量 和水的體積,這個體積是要通過那兩個杯子來實現,具體的實現方式有六種,分別是:
1、倒滿1,而2不動;
2、倒滿2,而1不動;
3、清空1,而2不動;
4、清空2,而1不動;
5、從1往2倒水;
6、從2往1倒水。
讓1,2杯子的任意一個杯子裏的水爲C,求最少用多少步。

思路:
BFS+記憶路徑

完整代碼:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;

int A,B,C;
int v[105][105];    //標記是否位訪問過狀態
struct node
{
    int prea;       //記錄容器A前一個的狀態
    int preb;       //記錄容器B前一個的狀態
    int a;          //A,B爲此事狀態
    int b;
    int step;       //走的步數
    int operation;  //六種操作
};
node way[105][105]; //記憶路徑

void Output(node s)     //輸出函數打印路徑
{
    if(s.prea==-1 && s.preb==-1)
    {
        return;
    }
    else
    {
        Output(way[s.prea][s.preb]);    //遞歸,打印操作
        switch(s.operation)             //這六種情況。注意:單詞不要打錯
        {
            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 bfs()      //廣度優先搜素
{
    //初始化
    node s;
    s.prea=-1;
    s.preb=-1;
    s.a=0;
    s.b=0;
    s.step=0;
    s.operation=-1;

    queue<node>q;
    while(!q.empty()) q.pop();      //記得先清空在存
    q.push(s);
    while(!q.empty())
    {
        s=q.front();
        q.pop();
        way[s.a][s.b]=s;
        if(s.a==C || s.b==C)
        {
            cout<<s.step<<endl;
            Output(s);
            return ;
        }
        v[s.a][s.b]=1;
        for(int i=1;i<=6;i++)           //六種操作情況
        {
            //第一種   給1注滿水
            if(i==1 && !v[A][s.b])
            {
                v[A][s.b]=1;
                node nex;
                nex.a=A;
                nex.b=s.b;
                nex.prea=s.a;
                nex.preb=s.b;
                nex.step=s.step+1;
                nex.operation=i;
                q.push(nex);
            }
            //第二種   給2注滿水
            if(i==2 && !v[s.a][B])
            {
                v[s.a][B]=1;
                node nex;
                nex.a=s.a;
                nex.b=B;
                nex.prea=s.a;
                nex.preb=s.b;
                nex.step=s.step+1;
                nex.operation=i;
                q.push(nex);
            }
            //第三種   倒掉1中的水
            if(i==3 && !v[0][s.b])
            {
                v[0][s.b]=1;
                node nex;
                nex.a=0;
                nex.b=s.b;
                nex.prea=s.a;
                nex.preb=s.b;
                nex.step=s.step+1;
                nex.operation=i;
                q.push(nex);
            }
            //第四種   倒掉2中的水
            if(i==4 && !v[s.a][0])
            {
                v[s.a][0]=1;
                node nex;
                nex.a=s.a;
                nex.b=0;
                nex.prea=s.a;
                nex.preb=s.b;
                nex.step=s.step+1;
                nex.operation=i;
                q.push(nex);
            }
            //第五種   將1倒入2中
            if(i==5)
            {
                int dx,dy;
                if(s.a+s.b>B)       //滿了還有剩餘
                {
                    dx=s.a+s.b-B;
                    dy=B;
                }
                else if(s.a+s.b<=B) //沒滿或者正好
                {
                    dx=0;
                    dy=s.a+s.b;
                }
                if(!v[dx][dy])
                {
                    v[dx][dy]=1;
                    node nex;
                    nex.a=dx;
                    nex.b=dy;
                    nex.prea=s.a;
                    nex.preb=s.b;
                    nex.step=s.step+1;
                    nex.operation=i;
                    q.push(nex);
                }
            }
            //第六種   將2倒入1中
            if(i==6)
            {
                int dx,dy;
                if(s.a+s.b>A)       //滿了還有剩餘
                {
                    dy=s.a+s.b-A;
                    dx=A;
                }
                else if(s.a+s.b<=A) //沒滿或者正好
                {
                    dy=0;
                    dx=s.a+s.b;
                }
                if(!v[dx][dy])
                {
                    v[dx][dy]=1;
                    node nex;
                    nex.a=dx;
                    nex.b=dy;
                    nex.prea=s.a;
                    nex.preb=s.b;
                    nex.step=s.step+1;
                    nex.operation=i;
                    q.push(nex);
                }
            }
        }
    }
    cout<<"impossible"<<endl;       //注意不要忘記"impossible"
    return;
}

int main()
{
    while(cin>>A>>B>>C)
    {
        memset(v,0,sizeof(v));
        bfs();
    }
    return 0;
}

原題鏈接:
https://vjudge.net/problem/POJ-3414
http://poj.org/problem?id=3414

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章