poj 3414 广搜

来源:互联网 发布:日记本软件 编辑:程序博客网 时间:2024/05/01 01:37

 

 

 

     如题:http://poj.org/problem?id=3414

    题目要求输入3个数A,B,C,分别代表第一个杯子可以装水的容量A,第二个杯子可以装水的容量B,要求输出通过6种操作,是否而已让2个杯子中出现C升水。

    给出6种操作。"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"。

   要求输出最少步数,和每一步执行的操作,如果无法完成,输出impossible。

 

   这一题步数输出就是BFS最短路算法,每一步的下一层就是6种操作执行后的状态。

   难点是对每一步的操作的输出需要记录。我使用了3个数组。f[x][y]=上一层x*100+上一层y,记录当前状态(x,y)上一层的横纵坐标,取出时只需fa[x][y]/100,fa[x][y]%100。

    然后用stats[x][y]数组记录状态(1,,2,3,4,5,,6)。char str[6][10]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};在递归输出时用stats数组的值作为下标输出。

 

  注意:题目没说,但其实是多组数据。

 

 

 

#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;

int vis[102][102];
short A,B,C;
char str[6][10]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
int f[102][102];
short stats[102][102];

void print(int a,int b)
{
 if(f[a][b]==-1) 
  return;
 int ta=f[a][b]/100;
 int tb=f[a][b]%100;
 print(ta,tb);
 printf("%s\n",str[stats[a][b]-1]);
}
struct node
{
 short a,b;
 int step;
};
int final_a,final_b;
int BFS(int a,int b)
{
 memset(vis,0,sizeof(vis));
 memset(f,0,sizeof(f));
 memset(stats,0,sizeof(stats));
 node u;
 u.a=a;
 u.b=b;
 u.step=0;
 f[u.a][u.b]=-1;
 vis[u.a][u.b]=1;
 queue<node>q;
 q.push(u);
 node v;
 while(!q.empty())
 {
  u=q.front();
  if(u.a==C||u.b==C)
  {
   final_a=u.a;
   final_b=u.b;
   return u.step;
   
  }
  q.pop();
  if(u.a!=A)  //装满a
  {
   v.a=A;
   v.b=u.b;
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
   q.push(v);
   vis[v.a][v.b]=1;
   f[v.a][v.b]=u.a*100+u.b;
   stats[v.a][v.b]=1;
   }
  }
  if(u.b!=B)  //装满b
  {
   v.a=u.a;
   v.b=B;
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
    q.push(v);
    vis[v.a][v.b]=1;
    f[v.a][v.b]=u.a*100+u.b;
    stats[v.a][v.b]=2;
   }
  }
  if(u.a!=0) //清空a
  {
   v.a=0;
   v.b=u.b;
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
    q.push(v);
    vis[v.a][v.b]=1;
   f[v.a][v.b]=u.a*100+u.b;
   stats[v.a][v.b]=3;
   }
  }
  if(u.b!=0) //清空b
  {
   v.a=u.a;
   v.b=0;
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
    q.push(v);
    vis[v.a][v.b]=1;
   f[v.a][v.b]=u.a*100+u.b;
   stats[v.a][v.b]=4;
   }
  }
  if(u.a!=0&&u.b!=B)  //pour(a,b)
  {
   if(B-u.b>=u.a)
   {
    v.a=0;
    v.b=u.b+u.a;
   }
   else
   {
    v.b=B;
    v.a=u.a-(B-u.b);
   }
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
    q.push(v);
    vis[v.a][v.b]=1;
   f[v.a][v.b]=u.a*100+u.b;
   stats[v.a][v.b]=5;
   }
  }
  if(u.b!=0&&u.a!=A) //pour(b,a)
  {
   if(A-u.a>=u.b)
   {
    v.b=0;
    v.a=u.a+u.b;
   }
   else
   {
    v.a=A;
    v.b=u.b-(A-u.a);
   }
   v.step=u.step+1;
   if(!vis[v.a][v.b])
   {
    q.push(v);
    vis[v.a][v.b]=1;
   f[v.a][v.b]=u.a*100+u.b;
   stats[v.a][v.b]=6;
   }
  }
 }
 return -1;
}
int main()
{
 while(~scanf("%d %d %d",&A,&B,&C))
 {
  int count=BFS(0,0);
  if(count==-1)
   printf("impossible\n");
  else
  {
   printf("%d\n",count);
   print(final_a,final_b);
  }
 }
 return 0;
}

 

0 0
原创粉丝点击