Poj 3414 Pots(BFS + 打印路径)

题意:给你两个水杯的容积和一个数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;	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值