poj 3414 Pots搜索BFS
题目;
如何只用两个容器装到c的水量
分析:
BFS题,只不过要记录路径,参考算法导论上的BFS算法(我是参考别人的程序的,又学到了新东西)。
在这里简单总结一下:见代码中的文字
#include <iostream>
#include <queue>
#include <cstring> using namespace std;
#define X 105
int a,b,c;
bool use[X][X];
///////此结构体为记录ab的水量以及总走过的次数
typedef struct
{
int a; //a的水量
int b; //b的水量
int step;//总次数
}Node;
//////此结构体用来记录未倾倒的情况
struct pn
{
int prea; //未倾倒时a的水量
int preb; //未倾倒时b的水量
}pn;
struct pn p[X][X];
void dfs(int x,int y)
{ //x当前a的水量,y当前b的水量
if(p[x][y].prea+p[x][y].preb!=0)
dfs(p[x][y].prea,p[x][y].preb);
int px = p[x][y].prea;//之前的罐子a的水量
int py = p[x][y].preb;//之前的罐子b的水量
/////当a当前的水量是满的并且之前的水量未满,及b的水量未变,只能是fill a
if(px!=a&&x==a&&y==py)
{
cout<<"FILL(1)"<<endl;
return;
}
/////当b当前的水量是满的并且之前的水量未满,及a的水量未变,只能是fill b
if(px==x&&y==b&&py!=b)
{
cout<<"FILL(2)"<<endl;
return;
}
///当之前a的水量还有并且现在的为空,及b的水量未发生变化,只能是drop1
if(!x&&px&&y==py)
{
cout<<"DROP(1)"<<endl;
return;
}
///当之前b的水量还有并且现在的为空,及a的水量未发生变化,只能是drop2
if(!y&&py&&px==x)
{
cout<<"DROP(2)"<<endl;
return;
}
///当两者的前后的总和一样,说明没有全倒或者灌水的情况,只能是ab之间的互倒
if(px+py==x+y)
{
if(!x||y==b)//当a为空时或者b已经满了的话(注意到a倒b时,可能倒不完的情况)
cout<<"POUR(1,2)"<<endl;
else //同理反之
cout<<"POUR(2,1)"<<endl;
return;
}
}
bool bfs()
{
memset(p,0,sizeof(p));
memset(use,false,sizeof(use));//两个清零
Node temp,temp1; //用两个结构体
queue<Node> nq;
temp.a = 0;
temp.b = 0;
temp.step = 0;
use[0][0] = true;
nq.push(temp);
while(!nq.empty())
{
temp = nq.front();
nq.pop();
if(temp.a==c||temp.b==c)//当恰好倾倒到c的情况
{
cout<<temp.step<<endl;
dfs(temp.a,temp.b);
return true;
}
///////////////////////////////////////start
temp1.step = temp.step+1; //开始时次数加一
////////////////////////////////fill a的情况
temp1.a = a;
temp1.b = temp.b;
if(!use[temp1.a][temp1.b])//未用过这种倒水情况
{
use[temp1.a][temp1.b] = true; //标记用过这种倒水情况
p[temp1.a][temp1.b].prea = temp.a;//把上一次的a的水量记录到结构体中
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
////////////////////////////////fill b的情况
temp1.a = temp.a;
temp1.b = b;
if(!use[temp1.a][temp1.b])
{
use[temp1.a][temp1.b] = true;
p[temp1.a][temp1.b].prea = temp.a;
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
////////////////////////////////drop a的情况
temp1.a = 0;
temp1.b = temp.b;
if(!use[temp1.a][temp1.b])
{
use[temp1.a][temp1.b] = true;
p[temp1.a][temp1.b].prea = temp.a;
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
////////////////////////////////drop b的情况
temp1.a = temp.a;
temp1.b = 0;
if(!use[temp1.a][temp1.b])
{
use[temp1.a][temp1.b] = true;
p[temp1.a][temp1.b].prea = temp.a;
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
//////////////////////////pour a to b的情况
temp1.a = 0;
temp1.b = temp.a+temp.b;
if(temp1.b>b) //注意a倒b时有可能倒不完,及倒完a前b已满
{
temp1.a = temp1.b - b;
temp1.b = b;
}
if(!use[temp1.a][temp1.b])
{
use[temp1.a][temp1.b] = true;
p[temp1.a][temp1.b].prea = temp.a;
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
//////////////////////////pour b to a的情况
temp1.a = temp.a+temp.b;
temp1.b = 0;
if(temp1.a>a)
{
temp1.b = temp1.a-a;
temp1.a = a;
}
if(!use[temp1.a][temp1.b])
{
use[temp1.a][temp1.b] = true;
p[temp1.a][temp1.b].prea = temp.a;
p[temp1.a][temp1.b].preb = temp.b;
nq.push(temp1);
}
}
return false;
}
int main()
{
freopen("sum.in","r",stdin);
freopen("sum.out","w",stdout);
while(cin>>a>>b>>c)
if(!bfs())//当不可能时
cout<<"impossible"<<endl;
return 0;
}