///这个题的意思就是:现在有两个空杯子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.
*/
POJ - 3414 Pots
最新推荐文章于 2021-01-28 15:10:37 发布