POJ 3414(BFS+路径记录)

题目链接:点击打开链接


题目大意:给你俩罐子,分别能装a和b容量的水,通过六种手段(罐子一或二装满;罐子一倒二里(倒不下倒满就停)或二倒一;罐子一或二倒光),使俩罐子任意一个的水容量变c


题目思路:其他跟平常的bfs差不多,本题的关键在于记录步骤以便最后输出,所以我在结构体加了记录步数的和记录操作的,记录操作的是个数组,里面的下标就是第几步干了什么事。


解题心得:其实这道题是我第一次遇到的需要记录步骤的BFS,所以刚开始就很慌张。然后就去查了题解,用了什么回溯啊之类的,代码很长也思路也有点乱,就更慌了..然后突然想到可以在结构体里面加数组来记录操作,就开始了。刚开始很慌,就感觉很难自己不会,写到一些卡的地方就更慌了感觉写不出来,然后硬着头皮加个变量(其实就是加个变量的事嘛..自己想可怕了)。第一次的时候出来10000多..后来发现是vis这个记录是否访问过的数组没用上..忘记了...很尴尬...用上以后更尴尬,直接不输出了.....然后就把中间的数值打出来,然后自己模拟,发现有几步消失了..之前num放while(!q.empty())里了,然后仔细一想不对啊,这样就每从队列取出一个元素都++了,后来就想到放结构体了...没想到后来还是wa了..找了个题解对拍,尼玛那个题解的输出步骤比我多很多,而且对于impossible的情况都判断不出来....后来又找了个题解发现了自己的错误,反反复复看了好几遍没看出来,又开始模拟....尼玛..."DROP(1)"复制粘贴后忘把1改成2了,结果出现了两个"DROP(1)"....QAQ...也就是说应该输出DROP(2)的时候输出的也是"DROP(1)"...太粗心了,白白浪费我这么久。所以这告诉我们首先遇到难题不要怕,都是纸老虎,然后就是细心细心细心!大哭


以下是代码(我感觉我的代码比我查到的那些题解都短很多,而且易懂很多,思路也清晰很多...)

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<string>
using namespace std;
struct node{
	int a,b,dir[105],num;
}x;
int main(){
	queue<node>q;
	int a,b,c,vis[105][105],m,n;
	string cao[6]={"FILL(1)","FILL(2)","POUR(1,2)","POUR(2,1)","DROP(1)","DROP(2)"};
	while(~scanf("%d%d%d",&m,&n,&c)){
		int flag=0;
		x.a=0,x.b=0,x.num=0;
		memset(vis,0,sizeof(vis));
		vis[0][0]=1;
		while(!q.empty()){
			q.pop();
		}
		q.push(x);
		while(!q.empty()){
			node temp=q.front(),dev;
			q.pop();
			if(temp.a==c||temp.b==c){
				printf("%d\n",temp.num);
				for(int i=1;i<=temp.num;i++){
					cout<<cao[temp.dir[i]]<<endl;
				}
				flag=1;
				break;
			}
			dev=temp;//1
			dev.a=m;
			if(!vis[dev.a][dev.b]){
				vis[dev.a][dev.b]=1;
				dev.dir[++dev.num]=0;
				q.push(dev);
			}
			dev=temp;//2
			dev.b=n;
			if(!vis[dev.a][dev.b]){
				vis[dev.a][dev.b]=1;
				dev.dir[++dev.num]=1;
				q.push(dev);
			}
			dev=temp;//3
			if(dev.a>n-dev.b){
				dev.a-=n-dev.b;
				dev.b=n;
				if(!vis[dev.a][dev.b]){
					vis[dev.a][dev.b]=1;
					dev.dir[++dev.num]=2;
					q.push(dev);
				}
			}
			else{
				dev.b+=dev.a;
				dev.a=0;
				if(!vis[dev.a][dev.b]){
					vis[dev.a][dev.b]=1;
					dev.dir[++dev.num]=2;
					q.push(dev);
				}
			}
			dev=temp;//4
			if(dev.b>m-dev.a){
				dev.b-=m-dev.a;
				dev.a=m;
				if(!vis[dev.a][dev.b]){
					vis[dev.a][dev.b]=1;
					dev.dir[++dev.num]=3;
					q.push(dev);
				}
			}
			else{
				dev.a+=dev.b;
				dev.b=0;
				if(!vis[dev.a][dev.b]){
					vis[dev.a][dev.b]=1;
					dev.dir[++dev.num]=3;
					q.push(dev);
				}
			}
			dev=temp;//5
			dev.a=0;
			if(!vis[dev.a][dev.b]){
				vis[dev.a][dev.b]=1;
				dev.dir[++dev.num]=4;
				q.push(dev);
			}
			dev=temp;//6
			dev.b=0;
			if(!vis[dev.a][dev.b]){
				vis[dev.a][dev.b]=1;
				dev.dir[++dev.num]=5;
				q.push(dev);
			}
		}
		if(!flag){
			printf("impossible\n");
		}
	}
	return 0;
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值