题目名称:Pots
题目链接:http://poj.org/problem?id=3414
题意:
给出了两个瓶子的容量A,B, 以及一个目标水量C,
对A、B可以有如下操作:
FILL(i) 将瓶 i 倒满水;
DROP(i) 将瓶 i 倒空;
POUR(i,j) 将瓶 i 的水倒到瓶 j 中,如果瓶 j 满了(或许有些水留在瓶 i ),或者瓶 i 空了,说明都倒到 j 中.
问经过哪几个操作后能使得任意一个瓶子的残余水量为C。若不可能得到则输出impossible
代码如下(直接用stl的queue):
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
const int INF=0x3ffffff;
int A,B,C;
int ans;
bool ok,vis[105][105];
struct Last
{
int x,y;
int lo;
}last[105][105]; //保存上一步骤两杯的水量和操作的编号
char dir[6][10]={"FILL(1)","FILL(2)","DROP(1)","DROP(2)","POUR(1,2)","POUR(2,1)"};
struct Node
{
int a,b;
int sum;
};
queue<Node> q;
void print(int a,int b)
{
if(a!=0||b!=0)
{
print(last[a][b].x,last[a][b].y);
printf("%s\n",dir[last[a][b].lo]);
}
}
void bfs(Node ss)
{
while(!q.empty())
q.pop();
q.push(ss);
while(!q.empty())
{
Node now=q.front();
q.pop();
if(now.a==C||now.b==C)
{
printf("%d\n",now.sum);
print(now.a,now.b);
return ;
}
Node tmp;
//FILL(1);
if(!vis[A][now.b])
{
vis[A][now.b]=true;
tmp.a=A;
tmp.b=now.b;
tmp.sum=now.sum+1;
last[A][now.b].x=now.a;
last[A][now.b].y=now.b;
last[A][now.b].lo=0;
q.push(tmp);
}
//FILL(2)
if(!vis[now.a][B])
{
vis[now.a][B]=true;
tmp.a=now.a;
tmp.b=B;
tmp.sum=now.sum+1;
last[now.a][B].x=now.a;
last[now.a][B].y=now.b;
last[now.a][B].lo=1;
q.push(tmp);
}
//DROP(1);
if(!vis[0][now.b])
{
vis[0][now.b]=true;
tmp.a=0;
tmp.b=now.b;
tmp.sum=now.sum+1;
last[0][now.b].x=now.a;
last[0][now.b].y=now.b;
last[0][now.b].lo=2;
q.push(tmp);
}
//DROP(2)
if(!vis[now.a][0])
{
vis[now.a][0]=true;
tmp.a=now.a;
tmp.b=0;
tmp.sum=now.sum+1;
last[now.a][0].x=now.a;
last[now.a][0].y=now.b;
last[now.a][0].lo=3;
q.push(tmp);
}
//POUR(1,2)
int w1=min(now.a,B-now.b);
if(!vis[now.a-w1][now.b+w1])
{
tmp.a=now.a-w1;
tmp.b=now.b+w1;
tmp.sum=now.sum+1;
last[now.a-w1][now.b+w1].x=now.a;
last[now.a-w1][now.b+w1].y=now.b;
last[now.a-w1][now.b+w1].lo=4;
vis[now.a-w1][now.b+w1]=true;
q.push(tmp);
}
//POUR(2,1)
int w2=min(A-now.a,now.b);
if(!vis[now.a+w2][now.b-w2])
{
tmp.a=now.a+w2;
tmp.b=now.b-w2;
tmp.sum=now.sum+1;
last[now.a+w2][now.b-w2].x=now.a;
last[now.a+w2][now.b-w2].y=now.b;
last[now.a+w2][now.b-w2].lo=5;
vis[now.a+w2][now.b-w2]=true;
q.push(tmp);
}
}
printf("impossible\n");
}
int main()
{
while(scanf("%d%d%d",&A,&B,&C)!=EOF)
{
memset(vis,false,sizeof(vis));
vis[0][0]=true;
Node que;
que.a=que.b=0;
que.sum=0;
bfs(que);
}
return 0;
}
手写queue(时间会快很多):
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Max = 101;
struct node
{
int ope;
int a;
int b;
node* pre;
}que[Max*Max]; //队列结点,ope记录第几种操作,a,b记录此结点两个pot的水数。
bool vis[Max][Max];
char str[6][10] = {"FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)", "POUR(1,2)", "POUR(2,1)"};
void print(node now)
{
if(now.pre!=NULL)
{
print(*now.pre);
cout<<str[now.ope]<<endl;
}
}
void bfs(int a,int b,int c) //手写queue
{
int steps=0;
int head=0,tail=1; //队列的开始和结尾
que[0].a=que[0].b=0;
que[0].pre=NULL;
while(tail-head>0)
{
int count=tail-head;
while(count--)
{
node now=que[head];
if(now.a==c||now.b==c)
{
cout<<steps<<endl;
print(now);
return;
}
//FILL(1);
if(!vis[a][now.b])
{
que[tail].ope = 0;
que[tail].a = a;
que[tail].b = now.b;
que[tail].pre = &que[head];
vis[a][now.b] = true;
tail ++;
}
//FILL(2)
if(!vis[now.a][b])
{
que[tail].ope = 1;
que[tail].a = now.a;
que[tail].b = b;
que[tail].pre = &que[head];
vis[now.a][b] = true;
tail ++;
}
//DROP(1);
if(!vis[0][now.b])
{
que[tail].ope = 2;
que[tail].a = 0;
que[tail].b = now.b;
que[tail].pre = &que[head];
vis[0][now.b] = true;
tail ++;
}
//DROP(2)
if(!vis[now.a][0])
{
que[tail].ope = 3;
que[tail].a = now.a;
que[tail].b = 0;
que[tail].pre = &que[head];
vis[now.a][0] = true;
tail ++;
}
//POUR(1,2)
int wat1 = min(now.a, b - now.b);
if(!vis[now.a - wat1][now.b + wat1])
{
que[tail].ope = 4;
que[tail].a = now.a - wat1;
que[tail].b = now.b + wat1;
que[tail].pre = &que[head];
vis[now.a - wat1][now.b + wat1] = true;
tail ++;
}
//POUR(2,1)
int wat2 = min(a - now.a, now.b);
if(!vis[now.a + wat2][now.b - wat2])
{
que[tail].ope = 5;
que[tail].a = now.a + wat2;
que[tail].b = now.b - wat2;
que[tail].pre = &que[head];
vis[now.a + wat2][now.b - wat2] = true;
tail ++;
}
head++;
}
steps++;
}
cout<<"impossible"<<endl;
}
int main()
{
int a,b,c;
cin>>a>>b>>c;
memset(vis,false,sizeof(vis));
vis[0][0]=true;
bfs(a,b,c);
return 0;
}