[NJUPSOJ]倒油问题

description:
There are \(3\) buckets, whose volume are \(a,b,c\) respectly. How can you get \(k\) \(L\) oil by the three buckets?
(Initially, the first bucket is full with \(a\) \(L\) oil.
solutiuon:
bfs, use unordered_set to avoid the repeat.
code:

#include<cstdio>
#include<queue>
#include<unordered_set>
using namespace std;
unordered_set<int> vis;
int k;
int s[3];
struct o {
	int a[3];
	int step;
};
inline int _hash(o t) {
	int H=0;
	for (int i = 0; i < 3; ++i) {
		H = 1000 * H + t.a[i];
	}
	return H;
}
inline bool check(o t) {
	for (int i = 0; i < 3; ++i)
		if (t.a[i] == k)return 1;
	return 0;
}
inline bool ok(o(t)) {
	for (int i = 0; i < 3; ++i)
		if (t.a[i] < 0 || t.a[i] > s[i])
			return 0;
	return 1;
}
void bfs() {
	if (a == k) {
		printf("yes\n0\n");
		return;
	}
	o start;
	start.a[0] = s[0];
	start.a[1] = start.a[2] = 0;
	start.step = 0;
	queue<o> q;
	q.push(start);
	while (!q.empty()) {
		o t = q.front();
		q.pop();
		for (int i = 0; i < 3; ++i)
			for (int j = 0; j < 3; ++j) {
				if (i == j)continue;
				o tmp = t;
				tmp.a[j] = t.a[i] + t.a[j];
				tmp.a[i] = 0;
				int H = _hash(tmp);
				if (ok(tmp) && !vis.count(H)) {
						++tmp.step;
						int H = _hash(tmp);
						vis.insert(H);
						q.push(tmp);
						if (check(tmp)) {
							printf("yes\n%d\n", tmp.step);
							return;
						}
				}
				tmp = t;
				int dlt = s[j] - t.a[j];
				tmp.a[j] = s[j];
				tmp.a[i] = t.a[i]-dlt;
				H = _hash(tmp);
				if (ok(tmp) && !vis.count(H)) {
					++tmp.step;
					int H = _hash(tmp);
					vis.insert(H);
					q.push(tmp);
					if (check(tmp)) {
						printf("yes\n%d\n", tmp.step);
						return;
					}
				}
			}
	}
	puts("no");
}
int main() {
	for (int i = 0; i < 3; ++i)
		scanf("%d", s + i);
	scanf("%d", &k);
	bfs();
}
posted @ 2021-03-03 08:44  _dwt  阅读(75)  评论(0)    收藏  举报