题意:给你两个水杯的容积和一个数m,让你在任意一个水杯中倒出一个m,求最小步数,和输出路径。六种操作。
题解:bfs六种操作。然后记录路径。用dfs反向查找路径。博主的方法比较笨,手写了一个队列,然后记录当前步是由队列中那一步到达的。具体看代码实现。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node {
int x; //第一杯水的当前的值
int y; //第二杯水的当前的值
int pre; //当前状态是由队列中哪一步的转化过来的编号
int prezt; // 当前状态是怎么得到的。
int step; // 步数
}que[100000];
int book[105][105]; // 标记数组
int head,tail; //队头和队尾
int result[100000]; // 结果数组。
int ans = 0; // 结果数组的下标
void print(int s){ // dfs反向打印路径,把结果存到result数组中
if(s != 0){
result[ans++] = que[s].prezt;
print(que[s].pre);
}
else {
result[ans++] = que[s].prezt;
return ;
}
}
int a,b,c;
void bfs(){
que[0].x = 0;
que[0].y = 0;
que[0].pre = 0;
que[0].prezt = 0;
que[0].step = 0;
head = tail = 0;
tail++; // 入队列
book[a][b] = 1;
while(head < tail){
node now = que[head];
int aa = head;
head++;
if(now.x == c || now.y == c){ //达到目标结果
printf("%d\n",now.step); // 输出最小步数
print(now.pre);
for(int i = ans ; i >= 0 ; i -- ){ //输出路径
if(result[i] == 1){
printf("FILL(1)\n");
}
else if(result[i] == 2){
printf("DROP(1)\n");
}
else if(result[i] == 3){
printf("POUR(1,2)\n");
}
else if(result[i] == 4){
printf("FILL(2)\n");
}
else if(result[i] == 5){
printf("DROP(2)\n");
}
else if(result[i] == 6){
printf("POUR(2,1)\n");
}
}
if(now.prezt == 1){ //因为无法记录当前步的路径,所以特判
printf("FILL(1)\n");
}
else if(now.prezt == 2){
printf("DROP(1)\n");
}
else if(now.prezt == 3){
printf("POUR(1,2)\n");
}
else if(now.prezt == 4){
printf("FILL(2)\n");
}
else if(now.prezt == 5){
printf("DROP(2)\n");
}
else if(now.prezt == 6){
printf("POUR(2,1)\n");
}
return ;
}
for(int i = 1 ; i <= 6 ; i++){
if(i == 1){ //向A中注满水
node next;
next.x = a;
next.y = now.y;
next.step = now.step + 1;
next.pre = aa;
next.prezt = 1;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
else if(i == 2){ // 把A中水倒空
node next;
next.x = 0;
next.y = now.y;
next.step = now.step + 1;
next.pre = aa;
next.prezt = 2;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
else if(i == 3){ // 把A中水倒入B中
node next;
int sum = now.x + now.y;
if(sum <= b){
next.x = 0;
next.y = sum;
}
else if(sum >b){
next.x = sum - b;
next.y = b;
}
next.step = now.step + 1;
next.pre = aa;
next.prezt = 3;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
else if(i == 4){ // 把B中水倒满
node next;
next.x = now.x;
next.y = b;
next.step = now.step + 1;
next.pre = aa;
next.prezt = 4;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
else if(i == 5){ // 把B中水倒空
node next;
next.x = now.x;
next.y = 0;
next.step = now.step + 1;
next.pre = aa;
next.prezt = 5;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
else if(i == 6){ // 把B中水导入A中。
node next;
int sum = now.x + now.y;
if(sum <= a){
next.x = sum;
next.y = 0;
}
else{
next.x = a;
next.y = sum - a;
}
next.step = now.step + 1;
next.pre = aa;
next.prezt = 6;
if(book[next.x][next.y] == 0){
book[next.x][next.y] = 1;
que[tail] = next;
tail++;
}
}
}
}
printf("impossible\n");
return ;
}
int main(){
while(~scanf("%d%d%d",&a,&b,&c)){
memset(que,0,sizeof(que)); //清空队列
memset(book,0,sizeof(book)); //清空标记数组
ans = tail = head = 0; //初始化队列
memset(result,0,sizeof(result)); // 清空结果数组
bfs();
}
return 0;
}