POJ - 3414 Pots

///这个题的意思就是:现在有两个空杯子x y(容量),然后往里面倒水,接下来它们之间有几个操作(怎样倒水):x->empty,x->full,x->y,y->empty,y->full,y->x;
///再给出一个数z,问:什么时候某一个杯子的水的体积等于z,然后就完成了。。
///当然题目不会这么easy,它需要的是你倒的次数和你倒的过程,看看上面就知道倒的次数了;那么问题来了,怎么记录它的过程呢,这也是很烦的;
///我们可以用一个类似于链表的思想然后进行储存。回退 回退 回退  .......就形成了回溯了;
///所以这个题的核心就是bfs+模拟了,下面进行代码详解;
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
using namespace std;
const int maxn=1e3+7;
bool vis[maxn][maxn];
int k1,k2,k3;
struct node
{
    int x,y,step;///x,y分别代表两个杯子,step表示倾倒的次数;
    int pre,id,pos;///pre代表的某个节点的前一个信息,方便回溯,id代表它的位置信息,pos代表该位置下应该进行某种操作的进行角标记录;
}a[maxn];///运用链表的思想,将每个节点得位置信息及其步数情况进行记录

void bfs()
{
   memset(vis,0,sizeof(vis));
   node next,now;
   queue<node>q;
   stack<int>s;///这个栈是最巧妙的地方了,就是你需要回溯回去然后顺序输出的话是需要一个栈的操作来实现的
   a[0].pre=-1;
   int cnt=0;
   now.x=0;
   now.y=0;
   now.id=0;
   now.pos=0;
   now.step=0;
   now.pre=-1;
   ///方便在出栈的时候进行判断。。
   vis[now.x][now.y]=1;
   q.push(now);
   while(!q.empty())
   {
       now=q.front();
       q.pop();
       if(now.x==k3||now.y==k3)
       {
           printf("%d\n",now.step);
           int key=now.id;
           while(a[key].pre!=-1)
           {
               s.push(a[key].pos);
               key=a[key].pre;
           }·///回溯的思想;又想到了那个移动的光标的题目;
           for(int i=0;i<now.step;i++)
           {
               ///然后就是六种操作了;
               int k=s.top();
               if(k==1) printf("FILL(1)\n");
               else if(k==2) printf("DROP(1)\n");
               else if(k==3) printf("POUR(1,2)\n");
               else if(k==4) printf("FILL(2)\n");
               else if(k==5) printf("DROP(2)\n");
               else if(k==6) printf("POUR(2,1)\n");
               s.pop();
           }
           return ;
       }
       ///一共就是4种情况,x满,x空,y满,y空;
       ///然后再满的情况下又进行倒来倒去的情况,蛇皮操作就那几回。。
       if(now.x)
       {
          next=now;
          next.x=k1;///1->full,1;
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;///第几个位置;
              a[next.id].pos=1;
              a[next.id].pre=now.id;///将该位置的信息传递给pre
              q.push(next);
          }
          ///然后其他的题目是一样的;
          next=now;
          next.x=0;///1->empty;,2
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=2;
              a[next.id].pre=now.id;
              q.push(next);
          }
          next=now;
          next.x=now.x-(min(k2,now.y+now.x)-now.y);
          next.y=min(k2,now.x+now.y);///1->2;,3
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=3;
              a[next.id].pre=now.id;;
              q.push(next);
          }
       }
       else
       {
          next=now;
          next.x=k1;///1->full,1
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=1;
              a[next.id].pre=now.id;
              q.push(next);
          }
       }
       if(now.y)
       {
          next=now;
          next.y=k2;///2->full,4
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=4;
              a[next.id].pre=now.id;
              q.push(next);
          }
          next=now;
          next.y=0;///2->empty;,5
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=5;
              a[next.id].pre=now.id;
              q.push(next);
          }
          next=now;
          next.y=now.x-(min(k1,now.y+now.x)-now.y);
          next.x=min(k1,now.x+now.y);///2->1;
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[now.x][now.y]=1;
              next.id=++cnt;
              a[next.id].pos=6;
              a[next.id].pre=now.id;;
              q.push(next);
          }
       }
       else
       {
          next=now;
          next.y=k2;///2->full
          if(!vis[next.x][next.y])
          {
              next.step=now.step+1;
              vis[next.x][next.y]=1;
              next.id=++cnt;
              a[next.id].pos=4;
              a[next.id].pre=now.id;
              q.push(next);
          }
       }
   }
   printf("impossible\n");

}

int main ()
{
    scanf("%d %d %d",&k1,&k2,&k3);
    bfs();
    return 0;
}
/*
错误示范;
3 5 4
5
FILL(1)
POUR(1,2)
FILL(1)
POUR(2,1)
POUR(1,2)

Process returned 0 (0x0)   execution time : 1.211 s
Press any key to continue.

*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值