您的位置:首页 > 其它

POJ 3414 基础搜索 BFS 六

2017-02-12 11:45 323 查看
前一段时间看了题面,第一感觉就是自己肯定不会做,今天试了一下,尽然写出来了。

祝贺自己的进步吧~~^_^

  POJ 3414  Pot: http://poj.org/problem?id=3414
  题目大意:  给两个尿壶  大小为  A升和B升

  三种操作  : 把A或者B尿壶 倒空

                      把A或者B尿壶灌满

                     把A尿壶的水灌到B壶里面,如果B灌满了,就停止,A的壶剩着等待下一个操作,反过来是一样的。

  问: 怎么个倒法,能最少操作次数,灌出个 C升的水。

        要求输出最小次数,以及  如何操作!

  求最少次数还好,DFS不方便,BFS最快捷。

  但是怎么输出操作步骤呢?

  想了一段时间,我的解决方法是,每时刻,两壶里的水量 i,j ,都存储一个 上一状态的的倒法。 也就是存储,上一状态的i和j,以及倒法(用字母表示)

  用book来标记哪些水量倒出来过了,一旦C升的水倒出来了就进行输出操作。

  输出操作我是用递归倒着来解决。最终升的状态存储了上一次倒的状态以及倒法,而上一次的倒的状态,又存储了上上次的状态以及倒法。直到初始状态以后,就可以逐层输出啦。

  可能说的有点混。总结一下,我是

用BFS进行搜索最少次数,并同时记录每个状态的最少次数时,对应的上一状态(这里的“”最少“”依靠BFS的特性,不要纠结)。在BFS到了目标水量后,就用递归输出。

给出以下代码,不清楚的地方可以问,会更新。

BFS:

#include"cstdio"
#include"cstring"
#include"queue"
#include"algorithm"
using namespace std;
#define inf 109
#define loop(x,y,z) for(x=y;x<z;x++)

int a,b,c,sum;
int book[inf];
struct point
{int i,j;
point()
{

}
point(int x,int y)
{
i=x;j=y;
}
};
struct node
{
int li,lj;
char verb;
int cup;
int step;
void set(int i,int j,int k,char c)
{
li=i;lj=j;cup=k;verb=c;;
}
}pos[inf][inf];
queue<point>q;
void init()
{
while(!q.empty())q.pop();
memset(pos,-1,sizeof pos);
memset(book,0,sizeof book);
sum=0;
}

void print(int i,int j)
{
char x=pos[i][j].verb;
int y=pos[i][j].cup;
if(x=='F')
{
printf("FILL(%d)\n",y);
}
else if(x=='P')
{
int z=(y==1)?2:1;
printf("POUR(%d,%d)\n",y,z);
}
else if(x=='D')
{
printf("DROP(%d)\n",y);
}
}

void dfs(int i,int j)
{
if(i==0&&j==0)
{printf("%d\n",sum);return;}
sum++;
dfs(pos[i][j].li,pos[i][j].lj);
print(i,j);//printf("now dfs point is %d %d , and its next point is %d %d\n",i,j,pos[i][j].li,pos[i][j].lj);
}

point fill(int i,int j,int tag)
{
if(tag==0)i=a;
else j=b;
return point(i,j);
}

point drop(int i,int j,int tag)
{
if(tag==0)i=0;
else j=0;
return point(i,j);
}

point pour(int i,int j,int tag)
{
if(tag==0)
{
int t=i+j;
if(t>b)
{
j=b;
i=t-b;
}
else
{
j=t;
i=0;
}
}
else
{
int t=i+j;
if(t>a)
{
i=a;
j=t-a;
}
else
{
i=t;
j=0;
}
}
return point(i,j);
}

void bfs()
{
int i,j,x,y;
q.push(point(0,0)); //压入首点
book[0]=1; //标记首点
while(!q.empty())
{
point t=q.front(); //取出队首
q.pop(); //吐掉
for(i=0;i<6;i++)
{
point tag; //tag为变化后点
if(i<2)
{
tag=fill(t.i,t.j,i%2);
x=tag.i;
y=tag.j;
if(pos[x][y].li==-1&&pos[x][y].lj==-1) //如果变化后点未出现过
{
pos[x][y].set(t.i,t.j,i%2+1,'F'); //记录,标记,入队
book[x]=book[y]=1;
q.push(tag);
if(book[c]) //若出现目的水量,输出并结束
{
dfs(tag.i,tag.j);return;
}
}
}
else if(i<4) //下同
{
tag=drop(t.i,t.j,i%2);
x=tag.i;
y=tag.j;
if(pos[x][y].li==-1&&pos[x][y].lj==-1)
{
pos[x][y].set(t.i,t.j,i%2+1,'D');
book[x]=book[y]=1;
q.push(tag);
if(book[c])
{
dfs(tag.i,tag.j);return;
}
}
}
else
{
tag=pour(t.i,t.j,i%2);
x=tag.i;
y=tag.j;
if(pos[x][y].li==-1&&pos[x][y].lj==-1)
{
pos[x][y].set(t.i,t.j,i%2+1,'P');
book[x]=book[y]=1;
q.push(tag);
if(book[c])
{
dfs(tag.i,tag.j);return;
}
}
}

}

}
printf("impossible\n");
}

int main()
{
scanf("%d%d%d",&a,&b,&c);
init();
bfs();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: