POJ 3414 Pots

POJ 3414 Pots

bfs优先队列,把操作名称存入对应的下标,分六种情况讨论入队。

#include <iostream>
#include <stdio.h>
#include <queue>
#include <vector>
using namespace std;
const int N = 110;
int vis[N][N];
int point[N*N];
char option[][10] = {"#","FILL(1)","FILL(2)", "DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};  //操作
struct node
{
    int k1,k2;  //k1:第一杯水 k2:第二杯水
    int opnum;   //当前操作
    int nownum,prenum;   //当前下标,前驱
    int step;   //操作步数
    bool operator < (const node &c) const  //步数小的优先出队
    {
        return step > c.step;
    }
};
priority_queue<node> q;
vector<node> v;

void print(int num)   //打印路径
{
    int idx = 1;
    while(v[num].nownum) //存储下标
    {
        point[idx++] = v[num].nownum;
        num = v[num].prenum;
    }
    int i = idx-1;
    while(i) //输出
    {
        puts(option[v[point[i]].opnum]);
        i--;
    }
}

void bfs(int x,int y, int ans)
{
    bool flag = true;
    node now;
    now.k1 = now.k2 = now.nownum = now.prenum = now.step = 0;
    q.push(now);
    vis[0][0] = 1;
    v.push_back(now);
    int idx = 0;
    while(!q.empty())
    {
        now = q.top();
        q.pop();
        if(now.k1 == ans || now.k2 == ans)  //满足条件
        {
            flag =false;
            printf("%d
",now.step); //输出步数
            print(now.nownum);  //打印路径
            break;
        }
        node Next;
        for(int i = 1; i <= 6; i++)
        {
            if(i == 1)  //装满第一杯水
            {
                Next.k1 = x;
                Next.k2 = now.k2;
            }
            if(i == 2)  //装满第二杯水
            {
                Next.k1 = now.k1;
                Next.k2 = y;
            }
            if(i == 3)  //放干第一杯水
            {
                Next.k1 = 0;
                Next.k2 = now.k2;
            }
            if(i == 4) //放干第二杯水
            {
                Next.k1 = now.k1;
                Next.k2 = 0;
            }
            if(i == 5)  //第一杯水倒入第二杯水中
            {
                if(now.k1 + now.k2 <= y)  //不能装满或刚好装满第二杯水
                {
                    Next.k1 = 0;
                    Next.k2 = now.k1+now.k2;
                }
                else  //能够装满且还有剩余
                {
                    Next.k1 = now.k1 + now.k2 - y;
                    Next.k2 = y;
                }
            }
            if(i == 6) //第二杯水倒入一杯水中
            {
                 if(now.k1+now.k2 <= x) //不能或刚好装满
                 {
                     Next.k1 = now.k1 + now.k2;
                     Next.k2 = 0;
                 }
                 else //装满
                 { 
                     Next.k1 = x;
                     Next.k2 = now.k1 + now.k2 - x;
                 }
            }
            Next.opnum = i;  //记录当前操作下标
            if(!vis[Next.k1][Next.k2])
            {
                idx++;  //操作次数,当前的操作下标
                Next.nownum = idx;
                vis[Next.k1][Next.k2] = 1;
                Next.step = now.step + 1;
                Next.prenum = now.nownum;
                v.push_back(Next);
                q.push(Next);
            }
        }
    }
    if(flag) puts("impossible");
}
int main()
{
    int A,B,C;
    scanf("%d %d %d",&A,&B,&C);
    bfs(A,B,C);
    return 0;
}