POJ.3414 Pots (BFS)
POJ.3414 Pots (BFS)
题意分析
给你两个容器,分别能装下A升水和B升水,并且可以进行以下操作
FILL(i) 将第i个容器从水龙头里装满(1 ≤ i ≤ 2);
DROP(i) 将第i个容器抽干
POUR(i,j) 将第i个容器里的水倒入第j个容器(这次操作结束后产生两种结果,一是第j个容器倒满并且第i个容器依旧有剩余,二是第i个容器里的水全部倒入j中,第i个容器为空)
现在要求你写一个程序,来找出能使其中任何一个容器里的水恰好有C升,找出最少操作数并给出操作过程。
BFS时其实有6种操作,因为要考虑1向2中倒水是会不会将2倒满,2向1倒水的时候同理。
对于输出路径,可以用一个二维数组来保存状态,同时保存他的前驱节点。
最后输出的时候,需要用到一下栈来逆置。
代码总览
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#define nmax 105
using namespace std;
typedef struct{
int Anet;
int Bnet;
int time;
}pot;
int ansTimes,ansX,ansY;
typedef struct{
int type;
int X,Y;
bool isvisit;
}mes;
mes visit[nmax][nmax];
int A,B,C;
void bfs()
{
queue<pot> q;
while(!q.empty()) q.pop();
pot temp = {0,0,0},head;
q.push(temp);
visit[temp.Anet][temp.Bnet].isvisit = true;
visit[temp.Anet][temp.Bnet].type = -1;
while(!q.empty()){
head = q.front(); q.pop();
if(head.Anet == C || head.Bnet == C){
ansTimes = head.time;
ansX = head.Anet;
ansY = head.Bnet;
return;
}
for(int i = 1;i<=6;++i){
temp = head;
temp.time = head.time+1;
if(i == 1){
temp.Anet = A;
}else if(i == 2){
temp.Bnet = B;
}else if(i == 3){
temp.Anet = 0;
}else if(i == 4){
temp.Bnet = 0;
}else if(i == 5){
int k1 = temp.Anet, k2 = temp.Bnet;
if(k1+k2 < A){
temp.Anet = k1+k2;
temp.Bnet = 0;
}else{
temp.Anet = A;
temp.Bnet = k1+k2 - A;
}
}else if(i == 6){
int k1 = temp.Anet, k2 = temp.Bnet;
if(k1+k2 < B){
temp.Bnet = k1+k2;
temp.Anet = 0;
}else{
temp.Bnet = B;
temp.Anet = k1+k2 - B;
}
}
//printf("%d %d %d\n",temp.Anet,temp.Bnet,i);
if(visit[temp.Anet][temp.Bnet].isvisit == false){
//printf("OK FOR %d %d %d\n",temp.Anet,temp.Bnet,i);
q.push(temp);
//printf("%d\n",q.size());
visit[temp.Anet][temp.Bnet].isvisit = true;
visit[temp.Anet][temp.Bnet].type = i;
visit[temp.Anet][temp.Bnet].X = head.Anet;
visit[temp.Anet][temp.Bnet].Y = head.Bnet;
}
}
}
ansTimes = -1;
}
void output(int x, int y)
{
vector<string> v; v.clear();
int a = x,b = y;
while(visit[x][y].type != -1){
if(visit[x][y].type == 1){
v.push_back("FILL(1)");
}else if(visit[x][y].type == 2){
v.push_back("FILL(2)");
}else if(visit[x][y].type == 3){
v.push_back("DROP(1)");
}else if(visit[x][y].type == 4){
v.push_back("DROP(2)");
}else if(visit[x][y].type == 5){
v.push_back("POUR(2,1)");
}else{
v.push_back("POUR(1,2)");
}
a = visit[x][y].X;
b = visit[x][y].Y;
x = a;
y = b;
}
for(int i = v.size()-1;i>=0;--i){
printf("%s\n",v[i].c_str());
}
}
int main()
{
while(scanf("%d %d %d",&A,&B,&C)!= EOF){
memset(visit,0,sizeof(visit));
bfs();
if(ansTimes == -1){
printf("impossible\n");
}else{
printf("%d\n",ansTimes);
output(ansX,ansY);
}
}
return 0;
}