pots

题目链接:http://poj.org/problem?id=3414

 由于一直没有好好掌握搜索, 所以经常遇到搜索题就挂了,老师让我们默写我都写不出来。为了准备蓝桥杯以及之后的比赛,我下定决心好好学, 恢复以前的状态。

题意:bfs + 路径打印, 六种状态:A fill, A drop, B fill, B drop, A pour B, B pour A,  广搜不多说,直接上代码。打印路径: 记录A B剩余水的状态, 以上一次A B 剩余水量作为其前区节点, 定义一个结构体储存剩余水量, 每一次操作状态, 以及步数。 我做这题时收获不小, 这道题让我掌握了一点bfs, 还有就是遇到了一个坑点, 然后一直很揪心。原来的方法,每一次第一个输出的总是fill(1),花了好久时间发现问题。  问题:由于广搜的起点并不是六种操作, 所以第一步的状态就不能常规解决。 后来我想到在dfs打印路径时, 可以做一个判断, 因为刚开始A B 都是没有水的, 所以第一步操作只能是 fill(1)或fill(2),于是输出前做一个判断就OK了。

代码:

#include <iostream>
#include <stdio.h>
#include <queue>
#include <cstring>
using namespace std;

const int maxn = 1e2 + 5;
struct pot {
	int k1, k2, op;
};
struct path{
	int x, y, op, step;
}path[maxn][maxn];
char str[][10] = { "FILL(1)", "FILL(2)", "DROP(1)", "DROP(2)",  "POUR(2,1)", "POUR(1,2)"};
int A, B, C;
bool judge[maxn][maxn];
void my_clear() {
	struct path h = {0, 0, 0, 0};
	memset(judge, 0, sizeof(judge));
	for (int i = 0; i < maxn; i++)
		for (int j = 0; j < maxn; j++)
		path[i][j]= h;

}
// 递归打印路径 
void dfs(int x, int y) {
	int a = path[x][y].x;
	int b = path[x][y].y;

	if (path[x][y].step == 0) { //输出第一次操作 
		if (a == A)
			cout << str[0] << endl;
		if (b == B)
			cout << str[1] << endl; 
		return;
	}
	dfs(a, b);
	cout << str[path[x][y].op]<<  endl;
}
void BFS(int v1, int v2, int L) {
	queue <pot> wat;
	pot start = {0, 0, 0};
	judge[0][0] = true;
	wat.push(start);
	while (!wat.empty()) {
		pot tep = wat.front();
		wat.pop();
		int temp;
		if (tep.k1 == L || tep.k2 == L) {
			cout << path[tep.k1][tep.k2].step << endl;
			dfs(tep.k1, tep.k2);
			return ;
		}
		for (int i = 0; i < 6; i++) {
			switch(i) {
					/*6种状态*/ 
					case 0 : start.k1 = v1, start.k2 = tep.k2; break;  			//A fill
					case 2 : start.k1 = 0, start.k2 = tep.k2; break;				//A empty
					case 1 : start.k1 = tep.k1; start.k2 = v2; break;			//B fill
					case 3 : start.k1 = tep.k1; start.k2 = 0; break;			//B empty
					case 5 : temp = tep.k1 + tep.k2 - v2;					//A -> B
					 		 if (temp > 0) {
					 				start.k1 = temp;
					 				start.k2 = v2;
					 			}
					 		 else {
					 				start.k1 = 0;
					 				start.k2 = tep.k1 + tep.k2;
					 			}
					break;
					case 4 : temp = tep.k1 + tep.k2 - v1;						// B -> A
				     		 if (temp > 0) {
								start.k2 = temp;
								start.k1 = v1;
								}
							 else {
								start.k2 = 0;
								start.k1 = tep.k1 + tep.k2;
								}
					break;
			}
			if (!judge[start.k1][start.k2]) {
				path[start.k1][start.k2].x = tep.k1;
				path[start.k1][start.k2].y = tep.k2;//记录前驱结点 
				path[start.k1][start.k2].op = i;
				path[start.k1][start.k2].step = path[tep.k1][tep.k2].step + 1;				
				judge[start.k1][start.k2] = true;
				
				wat.push(start);
			}
		}
	}
	cout << "impossible" << endl;
}
int main()
{
	while (cin >> A >> B >> C) {
		BFS(A, B, C);
		my_clear();
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值