Pots

题目

样例

这道题是bfs加上回溯法,但是我不是很会回溯所以参考了大佬的方法,现在懂了怎么回溯了!

https://blog.csdn.net/qq_41658955/article/details/81290846

大佬的博客链接!

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 10005;
struct node
{
	int a;//当前a,b中水容量情况
	int b;
	int parent;//需要回溯路径,由父节点回溯
	string s;//由字符数组记录本节点的操作
	int time;//记录访问本节点开始时的步数
} link[maxn];
int vis[101][101];//标记数组,节点是否入队
//结点个数足够大
int aa, bb, cc;//aa和bb是函数的变换条件
int pp, qq;
int flag;//标记是否找到目标节点
bool judge(int x, int y)
{
	if (vis[x][y] == 1 || x<0 || y<0 || x>aa || y>bb)
		return false;
	else
		return true;
}
void bfs()
{
	int dis;
	while (pp < qq)
	{
		//每次搜索有六种操作,对应六种入队和坐标变换形式
		for (int i = 1; i <= 6; i++)
		{
			switch (i)
			{
			case 1:
				link[qq].a = aa;//将1桶倒满水
				link[qq].b = link[pp].b;//2桶水不变
				link[qq].time = link[pp].time + 1;
				link[qq].s = "FILL(1)";
				link[qq].parent = pp;
				break;
			case 2:
				link[qq].a = link[pp].a;
				link[qq].b = bb;
				link[qq].time = link[pp].time + 1;
				link[qq].s = "FILL(2)";
				link[qq].parent = pp;
				break;
			case 3:
				link[qq].a = link[pp].a;
				link[qq].b = link[pp].b;
				dis = bb - link[qq].b;//2桶满了需要的水
				if (link[qq].a >= dis)
				{
					link[qq].b = bb;
					link[qq].a -= dis;
				}
				else
				{
					link[qq].b += link[qq].a;
					link[qq].a = 0;
				}
				link[qq].time = link[pp].time + 1;
				link[qq].s = "POUR(1,2)";
				link[qq].parent = pp;
				break;
			case 4:
				link[qq].a = link[pp].a;
				link[qq].b = link[pp].b;
				dis = aa - link[qq].a;
				if (link[qq].b >= dis)
				{
					link[qq].a = aa;
					link[qq].b -= dis;
				}
				else
				{
					link[qq].a += link[qq].b;
					link[qq].b = 0;
				}
				link[qq].time = link[pp].time + 1;
				link[qq].s = "POUR(2,1)";
				link[qq].parent = pp;
				break;
			case 5:
				link[qq].a = 0;
				link[qq].b = link[pp].b;
				link[qq].time = link[pp].time + 1;
				link[qq].s = "DROP(1)";
				link[qq].parent = pp;
				break;
			case 6:
				link[qq].a = link[pp].a;
				link[qq].b = 0;
				link[qq].time = link[pp].time + 1;
				link[qq].s = "DROP(2)";
				link[qq].parent = pp;
				break;
			default:
				;
			}
			int xx = link[qq].a;
			int yy = link[qq].b;
			if (judge(xx, yy))
			{
				if (xx == cc || yy == cc)
				{
					///cout<<"目标节点找到"<<qq<<"是编号"<<endl;//检验
					flag = 1;
					return;
				}
				else
				{
					qq++;
					///cout<<qq<<"增加"<<"横纵坐标为"<<xx<<":"<<yy<<endl;//检验
					vis[xx][yy] = 1;
					//节点入队
				}
			}
		}
		pp++;//当前节点出队
		///cout<<pp<<"节点出队"<<endl;
	}
}
int main()
{
	cin >> aa >> bb >> cc;
	//cc是目标节点判定因素
	memset(vis, 0, sizeof(vis));
	pp = qq = 0;
	flag = 0;
	//完整的入队程序
	link[qq].a = 0;
	link[qq].b = 0;
	link[qq].time = 0;
	link[qq].parent = -1;
	link[qq].s = "start";
	vis[0][0] = 1;
	qq++;
	//入队程序结束
	bfs();
	//下面进行非常重要的一关:路径回溯
	stack<string>finds;//将节点的序号压入栈
	///cout<<qq<<endl;//检验qq值
	int p = qq;
	if (flag)
	{
		cout << link[p].time << endl;
		finds.push(link[p].s);
		while (link[p].parent)
		{
			p = link[p].parent;
			finds.push(link[p].s);
		}
		while (!finds.empty())
		{
			string s = finds.top();
			cout << s << endl;
			finds.pop();
		}
	}
	else
		cout << "impossible" << endl;
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值