poj 3414 Pots(bfs+輸出回溯路徑)

給你兩個容器,分別能裝下A升水和B升水,並且可以進行以下操作
FILL(i) 將第i個容器從水龍頭裏裝滿(1 ≤ i ≤ 2);
DROP(i) 將第i個容器抽乾
POUR(i,j) 將第i個容器裏的水倒入第j個容器(這次操作結束後產生兩種結果,一是第j個容器倒滿並且第i個容器依舊有剩餘,二是第i個容器裏的水全部倒入j中,第i個容器爲空)
現在要求你寫一個程序,來找出能使其中任何一個容器裏的水恰好有C升,找出最少操作數並給出操作過程

Input

有且只有一行,包含3個數A,B,C(1<=A,B<=100,C<=max(A,B))

Output
第一行包含一個數表示最小操作數K
隨後K行每行給出一次具體操作,如果有多種答案符合最小操作數,輸出他們中的任意一種操作過程,如果你不能使兩個容器中的任意一個滿足恰好C升的話,輸出“impossible”
Sample Input

3 5 4

Sample Output

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

哇~被自己菜哭了~我真的對回溯很不在行啊~對指針更不在行~我開始寫的node fr; 所以無論如何向回指,其實都指的自身,因爲fr已經被定義了;這也是爲何他們都用的數組,改變地址啊~菜哭了~

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

int a, b, c;
char ji[6][10] = {"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};//六種狀態
int vis[110][110];//標記兩個瓶子水量狀態是否經過

struct node{
    int x, y, step, flag;//x 第一個杯子的水量 y 第二個杯子的水量 step 走的深度 flag 標記此刻走路的選擇是六種狀態的哪一個
    node* pre;//回溯專用
};

queue<node>q;
stack<int>lu;//因爲回溯是逆序的所以符合棧的規則,先進先出

int bfs(){
    node fr[400], ne;
    ne.flag = 0; ne.pre = NULL; ne.step = 0; ne.x = 0; ne.y = 0;
    q.push(ne);
    vis[0][0] = 1;
    int sum = 0;
    int cnt = -1;
    while(!q.empty()){
        cnt++;
        fr[cnt] = q.front();
        //cout <<"fr.x = " << fr[cnt].x << " fr.y = " << fr[cnt].y << " fr.step = " << fr[cnt].step << endl;
        q.pop();
        if(fr[cnt].x == c || fr[cnt].y == c){
            sum = fr[cnt].step;
           // cout << "sum = " << sum<< endl;
            while(fr[cnt].pre != NULL){
                lu.push(fr[cnt].flag);
                //cout << "fr.flag = " <<fr[cnt].flag << endl;
                fr[cnt] = *(fr[cnt].pre);
            }
            return sum;
        }
        for(int i = 1; i <= 6; i++){//分別對應六種狀態的選擇
            switch(i){
                case 1:
                    ne.x = a;
                    ne.y = fr[cnt].y;
                    ne.flag = 1;
                    break;
                case 2:
                    ne.x = fr[cnt].x;
                    ne.y = b;
                    ne.flag = 2;
                    break;
                case 3:
                    ne.x = 0;
                    ne.y = fr[cnt].y;
                    ne.flag = 3;
                    break;
                case 4:
                    ne.x = fr[cnt].x;
                    ne.y = 0;
                    ne.flag = 4;
                    break;
                case 5:
                    if(fr[cnt].x + fr[cnt].y > b){
                        ne.x = fr[cnt].x - (b-fr[cnt].y);
                        ne.y = b;
                    }
                    else{
                        ne.x = 0;
                        ne.y = fr[cnt].x + fr[cnt].y;
                    }
                    ne.flag = 5;
                    break;
                case 6:
                    if(fr[cnt].x + fr[cnt].y > a){
                        ne.x = a;
                        ne.y = fr[cnt].y - (a-fr[cnt].x);
                    }
                    else{
                        ne.x = fr[cnt].x + fr[cnt].y;
                        ne.y = 0;
                    }
                    ne.flag = 6;
                    break;
            }
            if(vis[ne.x][ne.y])
                continue;
            vis[ne.x][ne.y] = 1;
            ne.step  = fr[cnt].step + 1;
            ne.pre = &fr[cnt];
            q.push(ne);
        }
    }
    return 0;
}

void print(){
    while(!lu.empty()){
        int i = lu.top();
        lu.pop();
        printf("%s\n", ji[i-1]);
    }
}

int main(){
    while(scanf("%d%d%d", &a, &b, &c) != EOF){
        memset(vis, 0, sizeof(vis));
        int sum = bfs();
        if(sum == 0)
            printf("impossible\n");
        else{
            printf("%d\n", sum);
            print();
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章