OpenJudge F:Pots

每次操作分为6种情况,可以利用队列进行BFS搜索,同时进行剪枝和记录,避免振荡和没必要的操作。

#include <cstdio>
#include <queue>
#include <cmath>
#include <vector>
#include <iostream>
using namespace std;

struct Op {
	int a, b;
	int step;
	int way;
	int id,last_id;
	Op(int _a,int _b,int _step,int _way,int _id,int _last_id):
		a(_a),b(_b),step(_step),way(_way),id(_id),last_id(_last_id){}
};

void print(vector<Op>& allOp,int id) {
	if (id == 0)return;
	print(allOp, allOp[id].last_id);
	if (allOp[id].way == 1)printf("FILL(1)\n");
	else if (allOp[id].way == 2)printf("FILL(2)\n");
	else if (allOp[id].way == 3)printf("DROP(1)\n");
	else if (allOp[id].way == 4)printf("DROP(2)\n");
	else if (allOp[id].way == 5)printf("POUR(1,2)\n");
	else if (allOp[id].way == 6)printf("POUR(2,1)\n");
}

int main() {
	int A = 0, B = 0, C = 0;
	scanf_s("%d%d%d", &A, &B, &C);
	vector<Op>allOp;
	bool _flag[105][105] = { {false} };
	Op* init = new Op(0, 0, 0, 0, 0, -1);
	_flag[0][0] = true;
	int id = 1;
	allOp.push_back(*init);
	bool flag = false;
	int it = 0;
	while (allOp.begin() + it != allOp.end()) {
		auto temp = allOp[it];
		if (temp.a == C || temp.b == C) {
			flag = true;
			break;
		}
		it++;
		//分为6个操作 a倒满:1 b倒满:2 a倒空:3 b倒空:4 a倒入b:5 b导入a:6
		if (temp.a != A&&temp.b != B && !_flag[A][temp.b]) {
			Op* new_op = new Op(A, temp.b, temp.step + 1, 1, id++, temp.id);
			allOp.push_back(*new_op);
			_flag[new_op->a][new_op->b] = true;
			delete new_op;
		}
		if (temp.b != B&&temp.a != A && !_flag[temp.a][B]) {
			Op* new_op = new Op(temp.a, B, temp.step + 1, 2, id++, temp.id);
			allOp.push_back(*new_op);
			_flag[new_op->a][new_op->b] = true;
			delete new_op;
		}
		if (temp.a != 0 && temp.b != 0 && !_flag[0][temp.b]) {
			Op* new_op = new Op(0, temp.b, temp.step + 1, 3, id++, temp.id);
			allOp.push_back(*new_op);
			_flag[new_op->a][new_op->b] = true;
			delete new_op;
		}
		if (temp.b != 0 && temp.a != 0 && !_flag[temp.a][0]) {
			Op* new_op = new Op(temp.a, 0, temp.step + 1, 4, id++, temp.id);
			allOp.push_back(*new_op);
			_flag[new_op->a][new_op->b] = true;
			delete new_op;
		}
		if (temp.b != B&&temp.a != 0) {
			Op* new_op = new Op(fmax(temp.a - B + temp.b, 0), fmin(temp.a + temp.b, B), temp.step + 1, 5, id, temp.id);
			if (!_flag[new_op->a][new_op->b]) {
				allOp.push_back(*new_op);
				_flag[new_op->a][new_op->b] = true;
				id++;
			}
			delete new_op;
		}
		if (temp.a != A&&temp.b != 0) {
			Op* new_op = new Op(fmin(temp.a + temp.b, A), fmax(temp.a - A + temp.b, 0), temp.step + 1, 6, id, temp.id);
			if (!_flag[new_op->a][new_op->b]) {
				allOp.push_back(*new_op);
				_flag[new_op->a][new_op->b] = true;
				id++;
			}
			delete new_op;
		}
	}
	if (!flag)printf("impossible\n");
	else {
		auto temp = allOp[it];
		printf("%d\n", temp.step);
		print(allOp, temp.id);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值