题目大意:给出两个空杯子,已知这两个空杯子的容量,有无限多的水,再给出要求得到的体积,找出一种方法,得到要求的体积
解决:BFS+路径记录
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
int ca,cb,n,ex,ey;
//有六种选择方案,记录的时候只需要记录下,方案的代号0-6即可
char p[6][20]={"fill A","fill B","pour B A","pour A B","empty A","empty B"};
//bfs离不开判断是否走过,否则会陷入死循环
bool vis[1000][1000];
struct node
{
int x,y;
node(){}
node(int xx,int yy):x(xx),y(yy){}
};
struct pos
{
int x,y;
int kind;
pos(){}
pos(int xx,int yy,int k):x(xx),y(yy),kind(k){}
};
//存储路径的数组,路径中存放该结点是从哪个结点扩展而来的
pos path[1000][1000];
void bfs()
{
queue<node> q;
q.push(node(0,0));
vis[0][0]=1;
node now;
path[0][0]=pos(-1,-1,0);
while(!q.empty())
{
now=q.front();
if(now.x==n ||now.y==n)return;
q.pop();
if(!vis[ca][now.y])
{//fill A的情况,不一定A为空才能fill A
vis[ca][now.y]=1;
q.push(node(ca,now.y));
path[ca][now.y]=pos(now.x,now.y,0);
if(ca==n){ ex=ca; ey=0; return; }
}
if(!vis[now.x][cb])
{
vis[now.x][cb]=1;
q.push(node(now.x,cb));
path[now.x][cb]=pos(now.x,now.y,1);
if(cb==n){ ex=0; ey=cb; return; }
}
if(now.x!=ca && now.y!=0 )
{//pour B A的情况,这要分两种状态,一种是将A倒满,一种是将B倒空
if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca])
{
vis[ca][now.x+now.y-ca]=1;
q.push(node(ca,now.x+now.y-ca));
path[ca][now.x+now.y-ca]=pos(now.x,now.y,2);
if(now.x+now.y-ca==n){ ex=ca; ey=now.x+now.y-ca; return;}
}
else if(now.x + now.y < ca && !vis[now.x+now.y][0])
{
vis[now.x+now.y][0]=1;
q.push(node(now.x+now.y,0));
path[now.x+now.y][0]=pos(now.x,now.y,2);
if(now.x+now.y==n){ ex=now.x+now.y; ey=0; return;}
}
}
if(now.y!=cb && now.x!=0)
{//pour A B的情况,一种是将B倒满,一种是将A倒空
if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb])
{
vis[now.x+now.y-cb][cb]=1;
q.push(node(now.x+now.y-cb,cb));
path[now.x+now.y-cb][cb]=pos(now.x,now.y,3);
if(now.x+now.y-cb==n){ ex=now.x+now.y-cb; ey=cb; return;}
}
else if(now.x + now.y < cb && !vis[0][now.x+now.y])
{
vis[0][now.x+now.y]=1;
q.push(node(0,now.x+now.y));
path[0][now.x+now.y]=pos(now.x,now.y,3);
if(now.x+now.y==n){ now.x=0; now.y=now.x+now.y; return;}
}
}
if(!vis[0][now.y])
{//empty A的情况,不一定A满了才能倒空
vis[0][now.y]=1;
q.push(node(0,now.y));
path[0][now.y]=pos(now.x,now.y,4);
}
if(!vis[now.x][0])
{//empty B的情况,不一定B满了才能倒空
vis[now.x][0]=1;
q.push(node(now.x,0));
path[now.x][0]=pos(now.x,now.y,5);
}
}
}
void print(int x,int y)
{
if(path[x][y].x!=-1 && path[x][y].y!=-1)
{
print(path[x][y].x,path[x][y].y);
printf("%s\n",p[path[x][y].kind]);
}
}
int main()
{
while(cin>>ca>>cb>>n)
{
memset(vis,0,sizeof(vis));
bfs();
print(ex,ey);
cout<<"success"<<endl;
}
system("pause");
return 0;
}
poj 3414和此题一模一样,但是下边代码,提供一种不同的记录路径的方式,用string来记录,从起始到当前扩展结点的所有路
经,而不是仅仅记录该结点是由哪个结点扩展来的。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <string>
using namespace std;
int ca,cb,n,ex,ey;
char p[6][20]={"FILL(1)","FILL(2)","POUR(2,1)","POUR(1,2)","DROP(1)","DROP(2)"};
bool vis[105][105];
struct node
{
int x,y;
int step;
//string 方法记录路径
string way;
node(){}
node(int xx,int yy,int s,string w):x(xx),y(yy),step(s),way(w){}
};
string res;
/*
struct pos
{
int x,y;
int kind;
pos(){}
pos(int xx,int yy,int k):x(xx),y(yy),kind(k){}
};
pos path[105][105];
*/
int bfs()
{
queue<node> q;
q.push(node(0,0,0,""));
vis[0][0]=1;
node now;
while(!q.empty())
{
now=q.front();
if(now.x==n ||now.y==n){res=now.way; return now.step;}
q.pop();
if(!vis[ca][now.y])
{
vis[ca][now.y]=1;
q.push(node(ca,now.y,now.step+1,now.way+"0"));
if(ca==n){
res=q.back().way;
return now.step+1;
}
}
if(!vis[now.x][cb])
{
vis[now.x][cb]=1;
q.push(node(now.x,cb,now.step+1,now.way+"1"));
if(cb==n){
res=q.back().way;
return now.step+1;
}
}
if(now.x!=ca && now.y!=0 )
{
if(now.x+now.y >= ca && !vis[ca][now.x+now.y-ca])
{
vis[ca][now.x+now.y-ca]=1;
q.push(node(ca,now.x+now.y-ca,now.step+1,now.way+"2"));
if(now.x+now.y-ca==n){
res=q.back().way;
return now.step+1;
}
}
else if(now.x + now.y < ca && !vis[now.x+now.y][0])
{
vis[now.x+now.y][0]=1;
q.push(node(now.x+now.y,0,now.step+1,now.way+"2"));
if(now.x+now.y==n){
res=q.back().way;
return now.step+1;
}
}
}
if(now.y!=cb && now.x!=0)
{
if(now.x+now.y >= cb && !vis[now.x+now.y-cb][cb])
{
vis[now.x+now.y-cb][cb]=1;
q.push(node(now.x+now.y-cb,cb,now.step+1,now.way+"3"));
if(now.x+now.y-cb==n){
res=q.back().way;
return now.step+1;
}
}
else if(now.x + now.y < cb && !vis[0][now.x+now.y])
{
vis[0][now.x+now.y]=1;
q.push(node(0,now.x+now.y,now.step+1,now.way+"3"));
if(now.x+now.y==n){
res=q.back().way;
return now.step+1;
}
}
}
if(!vis[0][now.y])
{
vis[0][now.y]=1;
q.push(node(0,now.y,now.step+1,now.way+"4"));
}
if(!vis[now.x][0])
{
vis[now.x][0]=1;
q.push(node(now.x,0,now.step+1,now.way+"5"));
}
}
return -1;
}
int main()
{
cin>>ca>>cb>>n;
memset(vis,0,sizeof(vis));
int t=bfs();
if(t >=0 )
{
cout<<t<<endl;
int n=res.size();
for(int i=0;i<n;i++)
puts(p[res[i]-'0']);
}
else cout<<"impossible"<<endl;
system("pause");
return 0;
}