程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3414 得到想要的容量 BFS

POJ 3414 得到想要的容量 BFS

編輯:C++入門知識


題目的大意是: 給你兩個容量固定的燒杯,容量分別是A和B,如何得到體積是C的水,只有如下操作是合法的

1. 裝滿A,從水源處獲得

2. 裝滿B

3, 將A倒給B,倒完後或者B倒滿了,或者A空了

4. 將B倒給A,倒完後或者A滿了,或者B空了

5. 將A清空

6. 將B清空


求出最少的步驟可以使得從最初兩個空杯,得到體積為C水,其中容量為C的水,可以放在任何一個容器中。

Sample Input

3 5 4
Sample Output

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


分析:此題的分類是BFS,不過自己想半天也沒有想清楚如何BFS,看了discussion裡的一些提示,才所有頓悟。

在BFS的過程中,當前的狀態是兩個數,ca,cb,描述當前a燒杯中有水ca,b燒杯中有水cb。

因為下一步只有六種選擇的情況,所以我們把這六個情況都枚舉出來,例如當權枚舉到stepi,如果經過這一步的操作,達到的狀態出現過,我們就不將新狀態放入隊列,

否則作為新的狀態放入隊列。


我們要記錄路徑,所以還要保留每個狀態之前的狀態,同時也有保存到達當前狀態的時候,經歷了多少步。

所以每個狀態裡面的有如下值:

1. 兩個燒杯的容量 2. 前一個狀態 3.到當前狀態步驟 4 到這個狀態所采用的操作。


代碼如下:

[cpp] 
#include <stdio.h> 
#include <memory.h> 
 
#define MAX_NUM 101 
#define MAX_Q MAX_NUM * MAX_NUM 
 
enum OPERATION 

    FILL1 = 0, FILL2, POUR12, POUR21, DROP1, DROP2, NONE 
}; 
 
struct Step 

    int liter1; 
    int liter2; 
    int stepID; 
 
    OPERATION operation; 
    int previous; 
 
    Step() 
    { 
 
    } 
    Step(int l1, int l2, int step, OPERATION op, int previous) 
    { 
        liter1 = l1; 
        liter2 = l2; 
        stepID = step; 
        operation = op; 
        this->previous = previous; 
 
    } 
}; 
 
struct Queue 

    Step steps[MAX_Q]; 
    int front; 
    int rear; 
 
 
    void ini() 
    { 
        memset(steps, 0, sizeof(steps)); 
        front = rear = 0; 
    } 
 
    void push(int l1, int l2, int step, int privous, OPERATION op) 
    { 
        steps[rear++] = Step(l1, l2, step, op, privous); 
    } 
 
 
}; 
 
bool visit[MAX_NUM][MAX_NUM]; 
Queue q; 
 
void PrintPath(int i) 

    if( i == -1) 
    { 
        return ; 
    } 
    PrintPath(q.steps[i].previous); 
 
    switch(q.steps[i].operation) 
    { 
    case FILL1: 
 
        printf("FILL(1)\n"); 
        break; 
 
    case FILL2: 
        printf("FILL(2)\n"); 
        break; 
 
    case POUR12: 
        printf("POUR(1,2)\n"); 
        break; 
 
    case POUR21: 
        printf("POUR(2,1)\n"); 
        break; 
 
    case DROP1: 
        printf("DROP(1)\n"); 
        break; 
 
    case DROP2: 
        printf("DROP(2)\n"); 
        break; 
    } 

void BFS(int a, int b, int c) 

    q.ini(); 
    q.push(0, 0, 0, -1, NONE); 
    visit[0][0] = true; 
    Step nxt,current; 
    while(q.rear > q.front) 
    { 
        current = q.steps[q.front++]; 
        if(current.liter1 == c || current.liter2 == c) 
        { 
            break; 
        } 
        OPERATION iOp; 
        for( int i = 0; i < 6; i++) 
        { 
            iOp = (OPERATION)i; 
            nxt = current; 
            switch(iOp) 
            { 
            case FILL1: 
                { 
                    //fill glass a 
                    if( !visit[a][nxt.liter2] ) 
                    { 
                        q.push(a, nxt.liter2, current.stepID + 1, q.front - 1, FILL1); 
                        visit[a][nxt.liter2] = true; 
                    } 
                    break; 
                } 
            case FILL2: 
                { 
                    if( !visit[nxt.liter1][b] ) 
                    { 
                        q.push(nxt.liter1, b, current.stepID + 1, q.front - 1, FILL2); 
                        visit[nxt.liter1][b] = true; 
                    } 
                    break; 
                } 
            case POUR12: 
                { 
                    int newA = current.liter1; 
                    int newB = current.liter2; 
                    if(newA + newB > b) 
                    { 
                        newA = newA + newB - b; 
                        newB = b; 
                    } 
                    else 
                    { 
                        newB = newA + newB; 
                        newA = 0; 
                         
                    } 
                    if(!visit[newA][newB]) 
                    { 
                        q.push(newA, newB, current.stepID + 1, q.front - 1, POUR12); 
 
                        visit[newA][newB] = true; 
                    } 
                    break; 
                } 
            case POUR21: 
                { 
                    int newA = current.liter1; 
                    int newB = current.liter2; 
 
                    if(newA + newB > a) 
                    { 
                         
                        newB = newA + newB - a; 
                        newA = a; 
                    } 
                    else 
                    { 
                        newA = newA + newB; 
                        newB = 0; 
                    } 
 
                    if(!visit[newA][newB]) 
                    { 
                        q.push(newA, newB, current.stepID + 1, q.front - 1, POUR21); 
 
                        visit[newA][newB] = true; 
                    } 
                    break; 
                } 
            case DROP1: 
                { 
                    if( !visit[0][nxt.liter2] ) 
                    { 
                        q.push(0, nxt.liter2, current.stepID + 1, q.front - 1, DROP1); 
                        visit[0][nxt.liter2] = true; 
                    } 
                    break; 
                } 
            case DROP2: 
                { 
                    if( !visit[nxt.liter1][0] ) 
                    { 
                        q.push(nxt.liter1, 0, current.stepID + 1, q.front - 1, DROP2); 
                        visit[nxt.liter1][0] = true; 
                    } 
                    break; 
                } 
            } 
        } 
    } 
    if( q.front == q.rear) 
    { 
        printf("impossible\n"); 
    } 
    else 
    { 
        printf("%d\n", q.steps[q.front-1].stepID); 
        PrintPath(q.front-1); 
    } 

 
int main() 

 
    int a,b,c; 
 
    while(scanf("%d%d%d", &a, &b, &c) != EOF) 
    { 
        memset(visit, 0, sizeof(visit)); 
        BFS(a, b, c); 
    } 
    return 0; 

編寫的時候犯了好幾個bug,導致半天都調不通
bug1, 在newA newB賦值的時候,將順序寫錯,忽略了兩個值存在依賴關系的事實。

bug2, 最後遍歷的時候,沒有寫front-1, 其實front在上次取完了的時候,就已經-1.


作者:hopeztm

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved