POJ3414 模拟倒水问题 BFS记录路径

4 篇文章 0 订阅


卧槽!被struct折服了!以后就用它了!


题目概述:

这道题就是经典的倒水问题,不禁感慨一句以前需要人脑来做的东西现在直接计算机模拟就够了。

给定三个数字,前两个数字表示的是两个桶的最大容量,第三个数字表达的是目标容量。一共有三种操作,分别是清空某桶,装满某桶,还有把一个桶里面的水倒入另一个桶(如果会溢出就只能刚好倒满,剩下的水留在自己的桶里)。要求输出最少的操作步数,并且要输出操作方法。

算法思想:

因为题目要求输出的是最少操作步数,就想到了用BFS来枚举各个状态,而且其实可枚举出来的状态真的很少呀。

然后vis[][]这个数组记录的是(i,j)这个水流组合现在有没有出现过,这个其实不止起了优化的作用,而是保证程序可以终止,因为假如输入的数据是一个无法达到的数据的话,这个程序就会无限期枚举下去,所以这个数组就是必要的。

知道了这些之后,仍然要解决路径的问题,那么解决方法就是开了一个struct,比我那个pair<int,int>不知高到哪里去,因为这个结构体可以存储string,然后用string连接的操作就可以把所有操作记录下来,实乃高招。哦也许读者认为很容易就想到但是我比较弱啊对不起 Orz。

希望代码分层明显的读者可以自然写几个子函数,但是我当时觉得没什么必要就没写了。

代码部分:

#include <iostream>
#include <queue>
#include <map>
#include <string>
using namespace std;
int a, b, c;
int vis[117][117] = { 0 };

struct node{
	int a_m, b_m;
	string step;
	node(int a_v, int b_v, string s_v) : a_m(a_v), b_m(b_v), step(s_v) {}
};

int main() {
	int a, b, c; bool flag = false;
	cin >> a >> b >> c;
	queue<node> q;
	node start(0, 0, "");
	node result(0, 0, "");
	q.push(start);
	vis[0][0] = 1;
	while (!q.empty()) {
		if (flag) break;
		node next = q.front();
		q.pop();
		if (next.a_m == c || next.b_m == c){
			flag = true;
			result = next;
		}
		if (next.a_m != 0) {
			node tmp = node(0, next.b_m, next.step + '1');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp); // We don't need to check whether this satisfy results
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != 0) {
			node tmp = node(next.a_m, 0, next.step + '2');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp); 
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m != a) {
			node tmp = node(a, next.b_m, next.step + '3');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != b) {
			node tmp = node(next.a_m, b, next.step + '4');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m != 0 && next.a_m+next.b_m <= b && next.b_m != b){
			node tmp = node(0, next.a_m + next.b_m, next.step + '5');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.a_m !=0 && next.a_m+next.b_m > b && next.b_m != b){
			node tmp = node(next.a_m+next.b_m-b, b, next.step + '5');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m !=0 && next.a_m+next.b_m <= a && next.a_m != a){
			node tmp = node(next.a_m + next.b_m, 0, next.step + '6');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
		if (next.b_m != 0 && next.a_m + next.b_m>a && next.a_m != a){
			node tmp = node(a, next.a_m+next.b_m-a, next.step + '6');
			if (!vis[tmp.a_m][tmp.b_m]) {
				q.push(tmp);
				vis[tmp.a_m][tmp.b_m] = 1;
			}
		}
	}

	if (!flag) cout << "impossible" << endl;
	else {
		cout << result.step.size() << endl;
		for (int i = 0; i < result.step.size(); i++){
			switch (result.step[i]) {
			case '1': cout << "DROP(1)" << endl; break;
			case '2': cout << "DROP(2)" << endl; break;
			case '3': cout << "FILL(1)" << endl; break;
			case '4': cout << "FILL(2)" << endl; break;
			case '5': cout << "POUR(1,2)" << endl; break;
			case '6': cout << "POUR(2,1)" << endl; break;
 			}
		}
	}
	
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值