题意:有两个有瓶子,容量给定,初始为空。有六个动作可以选择。求如何使得某个瓶子中剩下给定量的油。六个动作及相应序号如下:
1 fill A
2 fill B
3 empty A
4 empty B
5 pour A to B
6 pour B to A
思路:BFS。队列存放两个瓶子的油量以及得到此状态的前一状态在队列中的位置。flag[i][j]为得到AB瓶容量分别为i和j所做的动作序号。
#include <stdio.h>
#include <string.h>
#define N 1002
char output[7][10] = {"","fill A","fill B",
"empty A","empty B",
"pour A B","pour B A"};
int a,b,res,flag[N][N],q[N*N][3];
void print(int index){
int i;
if(index != 0){
print(q[index][2]);//递归输出前1动作
printf("%s\n",output[flag[q[index][0]][q[index][1]]]);
}
}
void bfs(){
int x,y,front,rear;
front = rear = -1;
q[++rear][0] = 0;
q[rear][1] = 0;
q[rear][2] = -1;
while(front < rear){
x = q[++front][0];
y = q[front][1];
if(x == res || y == res){
print(front);
return ;
}
if(x<a && !flag[a][y]){//动作1
flag[a][y] = 1;
q[++rear][0] = a;
q[rear][1] = y;
q[rear][2] = front;
}
if(y<b && !flag[x][b]){//动作2
flag[x][b] = 2;
q[++rear][0] = x;
q[rear][1] = b;
q[rear][2] = front;
}
if(x && !flag[0][y]){//动作3
flag[0][y] = 3;
q[++rear][0] = 0;
q[rear][1] = y;
q[rear][2] = front;
}
if(y && !flag[x][0]){//动作4
flag[x][0] = 4;
q[++rear][0] = x;
q[rear][1] = 0;
q[rear][2] = front;
}
if(x && y<b){//动作5
if(x <= b-y && !flag[0][y+x]){
flag[0][y+x] = 5;
q[++rear][0] = 0;
q[rear][1] = y+x;
q[rear][2] = front;
}
if(x > b-y &&!flag[x-b+y][b]){
flag[x-b+y][b] = 5;
q[++rear][0] = x-b+y;
q[rear][1] = b;
q[rear][2] = front;
}
}
if(x<a && y){//动作6
if(y <= a-x && !flag[x+y][0]){
flag[x+y][0] = 6;
q[++rear][0] = x+y;
q[rear][1] = 0;
q[rear][2] = front;
}
if(y > a-x && !flag[a][y-a+x]){
flag[a][y-a+x] = 6;
q[++rear][0] = a;
q[rear][1] = y-a+x;
q[rear][2] = front;
}
}
}
}
int main(){int i;
freopen("a.txt","r",stdin);
while(scanf("%d %d %d",&a,&b,&res)!=EOF){
int i,j;
memset(flag,0,sizeof(flag));
flag[0][0] = -1;
bfs();
printf("success\n");
}
return 0;
}