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;
}

猜你喜欢

转载自blog.csdn.net/ling_wang/article/details/81390013